@mattstack/rt-client 0.15.1 → 0.19.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 +30 -0
- package/dist/commands.d.ts +295 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +192 -14
- package/dist/pane-ref.d.ts +8 -0
- package/dist/settings/paths.d.ts +8 -0
- package/dist/settings/team-local-read.d.ts +7 -0
- package/package.json +1 -1
- package/src/client.ts +155 -3
- package/src/commands.ts +86 -5
- package/src/index.ts +28 -1
- package/src/pane-ref.ts +28 -0
- package/src/settings/paths.ts +11 -0
- package/src/settings/registry-defs.ts +1 -1
- package/src/settings/team-local-read.ts +18 -0
- package/src/settings/write.ts +24 -3
package/dist/index.js
CHANGED
|
@@ -205,7 +205,7 @@ function eventsList(payload, o = {}) {
|
|
|
205
205
|
}
|
|
206
206
|
function agentStart(a, o = {}) {
|
|
207
207
|
const payload = { repo: a.repo, cwd: a.cwd };
|
|
208
|
-
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs"]) {
|
|
208
|
+
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs", "env", "herdrSocket", "handle", "bg"]) {
|
|
209
209
|
if (a[k] !== undefined)
|
|
210
210
|
payload[k] = a[k];
|
|
211
211
|
}
|
|
@@ -268,11 +268,14 @@ function paneSend(a, o = {}) {
|
|
|
268
268
|
return rtCommand("pane:send", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
269
269
|
}
|
|
270
270
|
function paneFocus(a, o = {}) {
|
|
271
|
-
|
|
271
|
+
const payload = { paneId: a.paneId };
|
|
272
|
+
if (a.callerWorkspace !== undefined)
|
|
273
|
+
payload.callerWorkspace = a.callerWorkspace;
|
|
274
|
+
return rtCommand("pane:focus", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
272
275
|
}
|
|
273
276
|
function gateOpen(a, o = {}) {
|
|
274
277
|
const payload = { subject: a.subject, kind: a.kind, questions: a.questions };
|
|
275
|
-
for (const k of ["meta", "agent", "pane", "nudge"])
|
|
278
|
+
for (const k of ["meta", "agent", "pane", "nudge", "context", "origin"])
|
|
276
279
|
if (a[k] !== undefined)
|
|
277
280
|
payload[k] = a[k];
|
|
278
281
|
return rtCommand("gate:open", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
@@ -312,8 +315,93 @@ function gateSubscriptions(a, o = {}) {
|
|
|
312
315
|
payload[k] = a[k];
|
|
313
316
|
return rtCommand("gate:subscriptions", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
314
317
|
}
|
|
318
|
+
function herdStart(a, o = {}) {
|
|
319
|
+
const payload = { name: a.name, repo: a.repo, session: a.session };
|
|
320
|
+
if (a.hidden !== undefined)
|
|
321
|
+
payload.hidden = a.hidden;
|
|
322
|
+
return rtCommand("herd:start", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60000 });
|
|
323
|
+
}
|
|
324
|
+
function herdSpawn(a, o = {}) {
|
|
325
|
+
const payload = { herd: a.herd, job: a.job };
|
|
326
|
+
for (const k of ["brief", "dir", "model", "effort", "account", "disposable"])
|
|
327
|
+
if (a[k] !== undefined)
|
|
328
|
+
payload[k] = a[k];
|
|
329
|
+
return rtCommand("herd:spawn", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60000 });
|
|
330
|
+
}
|
|
331
|
+
function herdAsk(a, o = {}) {
|
|
332
|
+
const payload = { herd: a.herd, job: a.job, session: a.session, questions: a.questions };
|
|
333
|
+
for (const k of ["pane", "context"])
|
|
334
|
+
if (a[k] !== undefined)
|
|
335
|
+
payload[k] = a[k];
|
|
336
|
+
return rtCommand("herd:ask", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
337
|
+
}
|
|
338
|
+
function herdMilestone(a, o = {}) {
|
|
339
|
+
const payload = { herd: a.herd, job: a.job, session: a.session, artifact: a.artifact };
|
|
340
|
+
for (const k of ["pane", "summary"])
|
|
341
|
+
if (a[k] !== undefined)
|
|
342
|
+
payload[k] = a[k];
|
|
343
|
+
return rtCommand("herd:milestone", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
344
|
+
}
|
|
345
|
+
function herdAnswer(a, o = {}) {
|
|
346
|
+
return rtCommand("herd:answer", { gate: a.gate }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
347
|
+
}
|
|
348
|
+
function herdReport(a, o = {}) {
|
|
349
|
+
return rtCommand("herd:report", { herd: a.herd, job: a.job, body: a.body }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
350
|
+
}
|
|
351
|
+
function herdGates(a, o = {}) {
|
|
352
|
+
return rtCommand("herd:gates", { herd: a.herd }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
353
|
+
}
|
|
354
|
+
function herdStatus(a, o = {}) {
|
|
355
|
+
return rtCommand("herd:status", { herd: a.herd }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
356
|
+
}
|
|
357
|
+
function herdList(a = {}, o = {}) {
|
|
358
|
+
const payload = {};
|
|
359
|
+
if (a.all !== undefined)
|
|
360
|
+
payload.all = a.all;
|
|
361
|
+
return rtCommand("herd:list", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
362
|
+
}
|
|
363
|
+
function herdResume(a, o = {}) {
|
|
364
|
+
return rtCommand("herd:resume", { herd: a.herd, session: a.session }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
365
|
+
}
|
|
366
|
+
function herdClose(a, o = {}) {
|
|
367
|
+
return rtCommand("herd:close", { herd: a.herd, job: a.job }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
368
|
+
}
|
|
369
|
+
function herdAttend(a, o = {}) {
|
|
370
|
+
return rtCommand("herd:attend", { herd: a.herd, job: a.job, callerWorkspace: a.callerWorkspace }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60000 });
|
|
371
|
+
}
|
|
372
|
+
function herdWrapUp(a, o = {}) {
|
|
373
|
+
const payload = { herd: a.herd };
|
|
374
|
+
for (const k of ["closePanes", "dispose", "deleteJobDirs", "archiveRoom"])
|
|
375
|
+
if (a[k] !== undefined)
|
|
376
|
+
payload[k] = a[k];
|
|
377
|
+
return rtCommand("herd:wrap-up", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 120000 });
|
|
378
|
+
}
|
|
379
|
+
function herdStopHidden(_a, o = {}) {
|
|
380
|
+
return rtCommand("herd:stop-hidden", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
381
|
+
}
|
|
382
|
+
function bgEnsure(a = {}, o = {}) {
|
|
383
|
+
const payload = {};
|
|
384
|
+
if (a.claim !== undefined)
|
|
385
|
+
payload.claim = a.claim;
|
|
386
|
+
return rtCommand("bg:ensure", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 15000 });
|
|
387
|
+
}
|
|
388
|
+
function bgStatus(o = {}) {
|
|
389
|
+
return rtCommand("bg:status", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
390
|
+
}
|
|
391
|
+
function bgStop(o = {}) {
|
|
392
|
+
return rtCommand("bg:stop", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
393
|
+
}
|
|
394
|
+
function bgRelease(a, o = {}) {
|
|
395
|
+
return rtCommand("bg:release", { claim: a.claim }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
396
|
+
}
|
|
315
397
|
// src/commands.ts
|
|
316
398
|
var GATE_BY_PANE = "pane";
|
|
399
|
+
function gateOptionValue(o) {
|
|
400
|
+
return typeof o === "string" ? o : o.value;
|
|
401
|
+
}
|
|
402
|
+
function gateOptionLabel(o) {
|
|
403
|
+
return typeof o === "string" ? o : o.label || o.value;
|
|
404
|
+
}
|
|
317
405
|
var COMMAND_NAMES = [
|
|
318
406
|
"project-mrs:read",
|
|
319
407
|
"discussions:read",
|
|
@@ -391,6 +479,20 @@ var COMMAND_NAMES = [
|
|
|
391
479
|
"gate:subscribe",
|
|
392
480
|
"gate:unsubscribe",
|
|
393
481
|
"gate:subscriptions",
|
|
482
|
+
"herd:start",
|
|
483
|
+
"herd:resume",
|
|
484
|
+
"herd:status",
|
|
485
|
+
"herd:list",
|
|
486
|
+
"herd:close",
|
|
487
|
+
"herd:spawn",
|
|
488
|
+
"herd:gates",
|
|
489
|
+
"herd:ask",
|
|
490
|
+
"herd:milestone",
|
|
491
|
+
"herd:answer",
|
|
492
|
+
"herd:report",
|
|
493
|
+
"herd:attend",
|
|
494
|
+
"herd:stop-hidden",
|
|
495
|
+
"herd:wrap-up",
|
|
394
496
|
"hooks:repair",
|
|
395
497
|
"hooks:watch",
|
|
396
498
|
"sdm:catalog",
|
|
@@ -404,7 +506,11 @@ var COMMAND_NAMES = [
|
|
|
404
506
|
"worktree:list",
|
|
405
507
|
"worktree:restore",
|
|
406
508
|
"worktree:freshen",
|
|
407
|
-
"worktree:adopt"
|
|
509
|
+
"worktree:adopt",
|
|
510
|
+
"bg:ensure",
|
|
511
|
+
"bg:status",
|
|
512
|
+
"bg:stop",
|
|
513
|
+
"bg:release"
|
|
408
514
|
];
|
|
409
515
|
// src/relay.ts
|
|
410
516
|
var DEFAULT_WS_URL = "ws://127.0.0.1:9401/ws";
|
|
@@ -581,6 +687,26 @@ async function openSmartPane(herdr, anchorPaneId, opts = {}) {
|
|
|
581
687
|
}
|
|
582
688
|
return { paneId, placement };
|
|
583
689
|
}
|
|
690
|
+
// src/pane-ref.ts
|
|
691
|
+
var BG_PREFIX = "bg:";
|
|
692
|
+
function parsePaneRef(ref) {
|
|
693
|
+
if (ref.startsWith(BG_PREFIX)) {
|
|
694
|
+
return {
|
|
695
|
+
server: "bg",
|
|
696
|
+
paneId: ref.slice(BG_PREFIX.length)
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
server: "visible",
|
|
701
|
+
paneId: ref
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
function formatPaneRef(paneId, server) {
|
|
705
|
+
if (server === "visible") {
|
|
706
|
+
return paneId;
|
|
707
|
+
}
|
|
708
|
+
return BG_PREFIX + paneId;
|
|
709
|
+
}
|
|
584
710
|
// src/settings/resolve.ts
|
|
585
711
|
import { homedir as homedir4 } from "os";
|
|
586
712
|
import { join as join5 } from "path";
|
|
@@ -598,6 +724,9 @@ function userSettingsPath() {
|
|
|
598
724
|
function teamSettingsPath(team) {
|
|
599
725
|
return join3(teamsDir(), team, "mattstack", "settings.team.jsonc");
|
|
600
726
|
}
|
|
727
|
+
function teamLocalPath(team) {
|
|
728
|
+
return join3(home(), ".mattstack", "rt", "teams", `${team}.json`);
|
|
729
|
+
}
|
|
601
730
|
function machineSettingsPath() {
|
|
602
731
|
return join3(home(), ".mattstack", "user", "local", machineKey(), "settings.local.jsonc");
|
|
603
732
|
}
|
|
@@ -690,7 +819,7 @@ var REGISTRY = [
|
|
|
690
819
|
scopes: ["user"],
|
|
691
820
|
default: [],
|
|
692
821
|
merge: "replace",
|
|
693
|
-
description: "Event-bus glob rules that raise a desktop notification: [{pattern, category, title, message}]. pattern is matched against the events-bus topic (Bun.Glob semantics); title/message may interpolate `{field}` from the event payload. A fresh key, not an ownership-latch port, so a default is fine here."
|
|
822
|
+
description: "Event-bus glob rules that raise a desktop notification: [{pattern, category, title, message, subjectPrefix?, url?}]. pattern is matched against the events-bus topic (Bun.Glob semantics); title/message may interpolate `{field}` from the event payload, plus the computed `{question}` field (the event payload's first question label, `payload.questions[0].label`, empty string when absent); optional subjectPrefix matches the event payload's subject as a prefix. The optional url is interpolated the same way as title/message and becomes the notification's Open target; a gate rule should set it. A fresh key, not an ownership-latch port, so a default is fine here."
|
|
694
823
|
},
|
|
695
824
|
{
|
|
696
825
|
key: "rt.cron",
|
|
@@ -1706,10 +1835,23 @@ function explainSetting(key, opts = {}) {
|
|
|
1706
1835
|
return resolveDef(def, readStores(), opts).rows;
|
|
1707
1836
|
}
|
|
1708
1837
|
// src/settings/write.ts
|
|
1709
|
-
import { existsSync as existsSync3, mkdirSync, readFileSync as
|
|
1838
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync5, renameSync, unlinkSync, writeFileSync } from "fs";
|
|
1710
1839
|
import { applyEdits, modify, parseTree } from "jsonc-parser";
|
|
1711
1840
|
import { randomBytes } from "crypto";
|
|
1712
1841
|
import { dirname as dirname2 } from "path";
|
|
1842
|
+
|
|
1843
|
+
// src/settings/team-local-read.ts
|
|
1844
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
1845
|
+
function isJoinedTeam(team) {
|
|
1846
|
+
try {
|
|
1847
|
+
const parsed = JSON.parse(readFileSync4(teamLocalPath(team), "utf8"));
|
|
1848
|
+
return typeof parsed === "object" && parsed !== null && parsed.joinedByRt === true;
|
|
1849
|
+
} catch {
|
|
1850
|
+
return false;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
// src/settings/write.ts
|
|
1713
1855
|
var FORMAT = { tabSize: 2, insertSpaces: true, eol: `
|
|
1714
1856
|
` };
|
|
1715
1857
|
function refuse(message) {
|
|
@@ -1767,6 +1909,11 @@ function migratedFalseMessage(key, def) {
|
|
|
1767
1909
|
const legacyPart = def.legacyFile ? ` — it is still read from ${def.legacyFile}` : "";
|
|
1768
1910
|
return `"${key}" is not writable through the settings resolver yet${legacyPart}`;
|
|
1769
1911
|
}
|
|
1912
|
+
function refuseIfJoined(team) {
|
|
1913
|
+
if (isJoinedTeam(team)) {
|
|
1914
|
+
refuse(`this machine joined "${team}" by invite, so its clone is pull-only and team settings cannot be written here. Ask the team's owner to make this change. Member-proposed changes are tracked in MAT-415.`);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1770
1917
|
function resolveStorePath(scope, opts) {
|
|
1771
1918
|
if (scope === "user")
|
|
1772
1919
|
return userSettingsPath();
|
|
@@ -1777,6 +1924,7 @@ function resolveStorePath(scope, opts) {
|
|
|
1777
1924
|
if (!existsSync3(path)) {
|
|
1778
1925
|
refuse(`team store for "${opts.team}" does not exist (${path}) — clone/seed it before writing to it`);
|
|
1779
1926
|
}
|
|
1927
|
+
refuseIfJoined(opts.team);
|
|
1780
1928
|
return path;
|
|
1781
1929
|
}
|
|
1782
1930
|
const teams = listTeams();
|
|
@@ -1786,7 +1934,9 @@ function resolveStorePath(scope, opts) {
|
|
|
1786
1934
|
if (teams.length > 1) {
|
|
1787
1935
|
refuse(`multiple local team stores found (${teams.join(", ")}) — pass opts.team to choose one`);
|
|
1788
1936
|
}
|
|
1789
|
-
|
|
1937
|
+
const team = teams[0];
|
|
1938
|
+
refuseIfJoined(team);
|
|
1939
|
+
return teamSettingsPath(team);
|
|
1790
1940
|
}
|
|
1791
1941
|
function resolveStorePathForUnset(scope, opts) {
|
|
1792
1942
|
if (scope === "user")
|
|
@@ -1795,7 +1945,10 @@ function resolveStorePathForUnset(scope, opts) {
|
|
|
1795
1945
|
return machineSettingsPath();
|
|
1796
1946
|
if (opts.team !== undefined) {
|
|
1797
1947
|
const path = teamSettingsPath(opts.team);
|
|
1798
|
-
|
|
1948
|
+
if (!existsSync3(path))
|
|
1949
|
+
return null;
|
|
1950
|
+
refuseIfJoined(opts.team);
|
|
1951
|
+
return path;
|
|
1799
1952
|
}
|
|
1800
1953
|
const teams = listTeams();
|
|
1801
1954
|
if (teams.length === 0)
|
|
@@ -1803,7 +1956,9 @@ function resolveStorePathForUnset(scope, opts) {
|
|
|
1803
1956
|
if (teams.length > 1) {
|
|
1804
1957
|
refuse(`multiple local team stores found (${teams.join(", ")}) — pass opts.team to choose one`);
|
|
1805
1958
|
}
|
|
1806
|
-
|
|
1959
|
+
const team = teams[0];
|
|
1960
|
+
refuseIfJoined(team);
|
|
1961
|
+
return teamSettingsPath(team);
|
|
1807
1962
|
}
|
|
1808
1963
|
function seedHeader() {
|
|
1809
1964
|
return `// rt settings — created by \`rt settings set\`. JSONC: comments and trailing commas are fine.
|
|
@@ -1849,7 +2004,7 @@ function findDuplicateKey(node) {
|
|
|
1849
2004
|
function writeIntoStore(storePath, jsonPath, value, createIfMissing) {
|
|
1850
2005
|
let content;
|
|
1851
2006
|
if (existsSync3(storePath)) {
|
|
1852
|
-
content =
|
|
2007
|
+
content = readFileSync5(storePath, "utf8");
|
|
1853
2008
|
if (content.trim() === "") {
|
|
1854
2009
|
content = seedHeader();
|
|
1855
2010
|
} else {
|
|
@@ -1870,7 +2025,7 @@ function writeIntoStore(storePath, jsonPath, value, createIfMissing) {
|
|
|
1870
2025
|
writeTempThenRename(storePath, finalText);
|
|
1871
2026
|
}
|
|
1872
2027
|
function removeFromStore(storePath, jsonPath) {
|
|
1873
|
-
const content =
|
|
2028
|
+
const content = readFileSync5(storePath, "utf8");
|
|
1874
2029
|
if (content.trim() === "")
|
|
1875
2030
|
return false;
|
|
1876
2031
|
assertEditableJsonc(storePath, content);
|
|
@@ -1897,7 +2052,7 @@ function writeTempThenRename(storePath, finalText) {
|
|
|
1897
2052
|
}
|
|
1898
2053
|
}
|
|
1899
2054
|
// src/settings/identity.ts
|
|
1900
|
-
import { existsSync as existsSync4, readFileSync as
|
|
2055
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, realpathSync } from "fs";
|
|
1901
2056
|
|
|
1902
2057
|
// src/settings/exec.ts
|
|
1903
2058
|
async function runCapture(argv, opts = {}) {
|
|
@@ -2059,7 +2214,7 @@ async function resolveNameToIdentity(name, reposJsonPath) {
|
|
|
2059
2214
|
if (!existsSync4(reposJsonPath))
|
|
2060
2215
|
return null;
|
|
2061
2216
|
try {
|
|
2062
|
-
const index = JSON.parse(
|
|
2217
|
+
const index = JSON.parse(readFileSync6(reposJsonPath, "utf8"));
|
|
2063
2218
|
const path = index[name];
|
|
2064
2219
|
if (typeof path !== "string")
|
|
2065
2220
|
return null;
|
|
@@ -2084,6 +2239,7 @@ export {
|
|
|
2084
2239
|
readMrsByBranch,
|
|
2085
2240
|
readDiscussions,
|
|
2086
2241
|
readBranchCache,
|
|
2242
|
+
parsePaneRef,
|
|
2087
2243
|
parseIdentity,
|
|
2088
2244
|
paneSpawn,
|
|
2089
2245
|
paneSend,
|
|
@@ -2099,6 +2255,20 @@ export {
|
|
|
2099
2255
|
listRuns,
|
|
2100
2256
|
isMigrated,
|
|
2101
2257
|
identityFromRemote,
|
|
2258
|
+
herdWrapUp,
|
|
2259
|
+
herdStopHidden,
|
|
2260
|
+
herdStatus,
|
|
2261
|
+
herdStart,
|
|
2262
|
+
herdSpawn,
|
|
2263
|
+
herdResume,
|
|
2264
|
+
herdReport,
|
|
2265
|
+
herdMilestone,
|
|
2266
|
+
herdList,
|
|
2267
|
+
herdGates,
|
|
2268
|
+
herdClose,
|
|
2269
|
+
herdAttend,
|
|
2270
|
+
herdAsk,
|
|
2271
|
+
herdAnswer,
|
|
2102
2272
|
getSetting,
|
|
2103
2273
|
getRun,
|
|
2104
2274
|
getDef,
|
|
@@ -2107,10 +2277,13 @@ export {
|
|
|
2107
2277
|
gateSubscriptions,
|
|
2108
2278
|
gateSubscribe,
|
|
2109
2279
|
gatePark,
|
|
2280
|
+
gateOptionValue,
|
|
2281
|
+
gateOptionLabel,
|
|
2110
2282
|
gateOpen,
|
|
2111
2283
|
gateList,
|
|
2112
2284
|
gateClose,
|
|
2113
2285
|
gateAnswer,
|
|
2286
|
+
formatPaneRef,
|
|
2114
2287
|
explainSetting,
|
|
2115
2288
|
expandVariables,
|
|
2116
2289
|
eventsWait,
|
|
@@ -2142,6 +2315,10 @@ export {
|
|
|
2142
2315
|
chatAway,
|
|
2143
2316
|
chatArchive,
|
|
2144
2317
|
chatAck,
|
|
2318
|
+
bgStop,
|
|
2319
|
+
bgStatus,
|
|
2320
|
+
bgRelease,
|
|
2321
|
+
bgEnsure,
|
|
2145
2322
|
allDefs,
|
|
2146
2323
|
agentStart,
|
|
2147
2324
|
agentResume,
|
|
@@ -2153,5 +2330,6 @@ export {
|
|
|
2153
2330
|
GATE_BY_PANE,
|
|
2154
2331
|
DEFAULT_WS_URL,
|
|
2155
2332
|
DEFAULT_SOCK,
|
|
2156
|
-
COMMAND_NAMES
|
|
2333
|
+
COMMAND_NAMES,
|
|
2334
|
+
BG_PREFIX
|
|
2157
2335
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const BG_PREFIX = "bg:";
|
|
2
|
+
export type PaneServer = "visible" | "bg";
|
|
3
|
+
export interface PaneRef {
|
|
4
|
+
server: PaneServer;
|
|
5
|
+
paneId: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parsePaneRef(ref: string): PaneRef;
|
|
8
|
+
export declare function formatPaneRef(paneId: string, server: PaneServer): string;
|
package/dist/settings/paths.d.ts
CHANGED
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
export declare function userSettingsPath(): string;
|
|
13
13
|
/** ~/.mattstack/teams/<team>/mattstack/settings.team.jsonc — the team store. */
|
|
14
14
|
export declare function teamSettingsPath(team: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* ~/.mattstack/rt/teams/<team>.json: the machine-local team record. Mirrored
|
|
17
|
+
* from repo-tools/lib/team/team-local.ts's teamLocalPath, which is the
|
|
18
|
+
* authority: rt-client has no dependency on rt's lib/, so this literal is
|
|
19
|
+
* duplicated here rather than imported (same convention as `teamSettingsPath`
|
|
20
|
+
* and `userSettingsPath` above).
|
|
21
|
+
*/
|
|
22
|
+
export declare function teamLocalPath(team: string): string;
|
|
15
23
|
/**
|
|
16
24
|
* ~/.mattstack/user/local/<machineKey()>/settings.local.jsonc — the machine
|
|
17
25
|
* store, TRACKED and keyed per machine (path literals legal here only).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One field of the machine-local team record, for the write guard. The record
|
|
3
|
+
* itself is owned by repo-tools/lib/team/team-local.ts; this reads only what
|
|
4
|
+
* the guard needs and never writes.
|
|
5
|
+
*/
|
|
6
|
+
/** Unreadable, absent or malformed all read as false, so nothing that predates the field is refused. */
|
|
7
|
+
export declare function isJoinedTeam(team: string): boolean;
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -356,7 +356,7 @@ export function agentStart(
|
|
|
356
356
|
a: Commands["agent:start"]["payload"], o: RtClientOptions = {},
|
|
357
357
|
): Promise<RtResponse<AgentRecord>> {
|
|
358
358
|
const payload: Record<string, unknown> = { repo: a.repo, cwd: a.cwd };
|
|
359
|
-
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs"] as const) {
|
|
359
|
+
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs", "env", "herdrSocket", "handle", "bg"] as const) {
|
|
360
360
|
if (a[k] !== undefined) payload[k] = a[k];
|
|
361
361
|
}
|
|
362
362
|
return rtCommand<AgentRecord>("agent:start", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
@@ -441,7 +441,9 @@ export function paneFocus(
|
|
|
441
441
|
a: Commands["pane:focus"]["payload"],
|
|
442
442
|
o: RtClientOptions = {},
|
|
443
443
|
): Promise<RtResponse<Commands["pane:focus"]["data"]>> {
|
|
444
|
-
|
|
444
|
+
const payload: Record<string, unknown> = { paneId: a.paneId };
|
|
445
|
+
if (a.callerWorkspace !== undefined) payload.callerWorkspace = a.callerWorkspace;
|
|
446
|
+
return rtCommand<Commands["pane:focus"]["data"]>("pane:focus", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
445
447
|
}
|
|
446
448
|
|
|
447
449
|
// ─── Gates (BOARD-20/21 gate facility) ─────────────────────────────────────
|
|
@@ -451,7 +453,7 @@ export function gateOpen(
|
|
|
451
453
|
o: RtClientOptions = {},
|
|
452
454
|
): Promise<RtResponse<Commands["gate:open"]["data"]>> {
|
|
453
455
|
const payload: Record<string, unknown> = { subject: a.subject, kind: a.kind, questions: a.questions };
|
|
454
|
-
for (const k of ["meta", "agent", "pane", "nudge"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
456
|
+
for (const k of ["meta", "agent", "pane", "nudge", "context", "origin"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
455
457
|
return rtCommand<Commands["gate:open"]["data"]>("gate:open", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
456
458
|
}
|
|
457
459
|
|
|
@@ -519,3 +521,153 @@ export function gateSubscriptions(
|
|
|
519
521
|
for (const k of ["session", "live"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
520
522
|
return rtCommand<Commands["gate:subscriptions"]["data"]>("gate:subscriptions", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
521
523
|
}
|
|
524
|
+
|
|
525
|
+
// ─── Herd (shepherd run registry) ───────────────────────────────────────────
|
|
526
|
+
|
|
527
|
+
/** Provisions the room, workspace and subscription before it answers, so it
|
|
528
|
+
gets the same 60s budget as a spawn rather than the 10s default. */
|
|
529
|
+
export function herdStart(
|
|
530
|
+
a: Commands["herd:start"]["payload"],
|
|
531
|
+
o: RtClientOptions = {},
|
|
532
|
+
): Promise<RtResponse<Commands["herd:start"]["data"]>> {
|
|
533
|
+
const payload: Record<string, unknown> = { name: a.name, repo: a.repo, session: a.session };
|
|
534
|
+
if (a.hidden !== undefined) payload.hidden = a.hidden;
|
|
535
|
+
return rtCommand<Commands["herd:start"]["data"]>("herd:start", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60_000 });
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/** Worktree provision plus agent launch; the 10s default cannot cover it. */
|
|
539
|
+
export function herdSpawn(
|
|
540
|
+
a: Commands["herd:spawn"]["payload"],
|
|
541
|
+
o: RtClientOptions = {},
|
|
542
|
+
): Promise<RtResponse<Commands["herd:spawn"]["data"]>> {
|
|
543
|
+
const payload: Record<string, unknown> = { herd: a.herd, job: a.job };
|
|
544
|
+
for (const k of ["brief", "dir", "model", "effort", "account", "disposable"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
545
|
+
return rtCommand<Commands["herd:spawn"]["data"]>("herd:spawn", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60_000 });
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export function herdAsk(
|
|
549
|
+
a: Commands["herd:ask"]["payload"],
|
|
550
|
+
o: RtClientOptions = {},
|
|
551
|
+
): Promise<RtResponse<Commands["herd:ask"]["data"]>> {
|
|
552
|
+
const payload: Record<string, unknown> = { herd: a.herd, job: a.job, session: a.session, questions: a.questions };
|
|
553
|
+
for (const k of ["pane", "context"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
554
|
+
return rtCommand<Commands["herd:ask"]["data"]>("herd:ask", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function herdMilestone(
|
|
558
|
+
a: Commands["herd:milestone"]["payload"],
|
|
559
|
+
o: RtClientOptions = {},
|
|
560
|
+
): Promise<RtResponse<Commands["herd:milestone"]["data"]>> {
|
|
561
|
+
const payload: Record<string, unknown> = { herd: a.herd, job: a.job, session: a.session, artifact: a.artifact };
|
|
562
|
+
for (const k of ["pane", "summary"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
563
|
+
return rtCommand<Commands["herd:milestone"]["data"]>("herd:milestone", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function herdAnswer(
|
|
567
|
+
a: Commands["herd:answer"]["payload"],
|
|
568
|
+
o: RtClientOptions = {},
|
|
569
|
+
): Promise<RtResponse<Commands["herd:answer"]["data"]>> {
|
|
570
|
+
return rtCommand<Commands["herd:answer"]["data"]>("herd:answer", { gate: a.gate }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/** A disposable job's report also closes its pane, one herdr CLI call under the runner's own 15s budget. */
|
|
574
|
+
export function herdReport(
|
|
575
|
+
a: Commands["herd:report"]["payload"],
|
|
576
|
+
o: RtClientOptions = {},
|
|
577
|
+
): Promise<RtResponse<Commands["herd:report"]["data"]>> {
|
|
578
|
+
return rtCommand<Commands["herd:report"]["data"]>("herd:report", { herd: a.herd, job: a.job, body: a.body }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export function herdGates(
|
|
582
|
+
a: Commands["herd:gates"]["payload"],
|
|
583
|
+
o: RtClientOptions = {},
|
|
584
|
+
): Promise<RtResponse<Commands["herd:gates"]["data"]>> {
|
|
585
|
+
return rtCommand<Commands["herd:gates"]["data"]>("herd:gates", { herd: a.herd }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export function herdStatus(
|
|
589
|
+
a: Commands["herd:status"]["payload"],
|
|
590
|
+
o: RtClientOptions = {},
|
|
591
|
+
): Promise<RtResponse<Commands["herd:status"]["data"]>> {
|
|
592
|
+
return rtCommand<Commands["herd:status"]["data"]>("herd:status", { herd: a.herd }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
export function herdList(
|
|
596
|
+
a: Commands["herd:list"]["payload"] = {},
|
|
597
|
+
o: RtClientOptions = {},
|
|
598
|
+
): Promise<RtResponse<Commands["herd:list"]["data"]>> {
|
|
599
|
+
const payload: Record<string, unknown> = {};
|
|
600
|
+
if (a.all !== undefined) payload.all = a.all;
|
|
601
|
+
return rtCommand<Commands["herd:list"]["data"]>("herd:list", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function herdResume(
|
|
605
|
+
a: Commands["herd:resume"]["payload"],
|
|
606
|
+
o: RtClientOptions = {},
|
|
607
|
+
): Promise<RtResponse<Commands["herd:resume"]["data"]>> {
|
|
608
|
+
return rtCommand<Commands["herd:resume"]["data"]>("herd:resume", { herd: a.herd, session: a.session }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/** Closes a herdr pane, one CLI call under the runner's own 15s budget. */
|
|
612
|
+
export function herdClose(
|
|
613
|
+
a: Commands["herd:close"]["payload"],
|
|
614
|
+
o: RtClientOptions = {},
|
|
615
|
+
): Promise<RtResponse<Commands["herd:close"]["data"]>> {
|
|
616
|
+
return rtCommand<Commands["herd:close"]["data"]>("herd:close", { herd: a.herd, job: a.job }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/** Three sequential herdr CLI calls (pane get, tab create, pane run), each under the runner's own 15s budget. */
|
|
620
|
+
export function herdAttend(
|
|
621
|
+
a: Commands["herd:attend"]["payload"],
|
|
622
|
+
o: RtClientOptions = {},
|
|
623
|
+
): Promise<RtResponse<Commands["herd:attend"]["data"]>> {
|
|
624
|
+
return rtCommand<Commands["herd:attend"]["data"]>("herd:attend", { herd: a.herd, job: a.job, callerWorkspace: a.callerWorkspace }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 60_000 });
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/** Closes panes, disposes worktrees and archives the room in one pass; the
|
|
628
|
+
worktree disposals alone can outrun a spawn's budget. */
|
|
629
|
+
export function herdWrapUp(
|
|
630
|
+
a: Commands["herd:wrap-up"]["payload"],
|
|
631
|
+
o: RtClientOptions = {},
|
|
632
|
+
): Promise<RtResponse<Commands["herd:wrap-up"]["data"]>> {
|
|
633
|
+
const payload: Record<string, unknown> = { herd: a.herd };
|
|
634
|
+
for (const k of ["closePanes", "dispose", "deleteJobDirs", "archiveRoom"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
635
|
+
return rtCommand<Commands["herd:wrap-up"]["data"]>("herd:wrap-up", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 120_000 });
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/** Runs `herdr session stop`, one CLI call under the runner's own 15s budget. */
|
|
639
|
+
export function herdStopHidden(
|
|
640
|
+
_a: Commands["herd:stop-hidden"]["payload"],
|
|
641
|
+
o: RtClientOptions = {},
|
|
642
|
+
): Promise<RtResponse<Commands["herd:stop-hidden"]["data"]>> {
|
|
643
|
+
return rtCommand<Commands["herd:stop-hidden"]["data"]>("herd:stop-hidden", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// ─── Background server (daemon-owned background herdr session) ────────────
|
|
647
|
+
|
|
648
|
+
/** May spawn `herdr server` and wait for it to bind; budget matches bg-service's own 10s readyTimeoutMs plus margin. */
|
|
649
|
+
export function bgEnsure(
|
|
650
|
+
a: Commands["bg:ensure"]["payload"] = {},
|
|
651
|
+
o: RtClientOptions = {},
|
|
652
|
+
): Promise<RtResponse<Commands["bg:ensure"]["data"]>> {
|
|
653
|
+
const payload: Record<string, unknown> = {};
|
|
654
|
+
if (a.claim !== undefined) payload.claim = a.claim;
|
|
655
|
+
return rtCommand<Commands["bg:ensure"]["data"]>("bg:ensure", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 15_000 });
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/** Never ensures/spawns; a plain read of the current state. */
|
|
659
|
+
export function bgStatus(o: RtClientOptions = {}): Promise<RtResponse<Commands["bg:status"]["data"]>> {
|
|
660
|
+
return rtCommand<Commands["bg:status"]["data"]>("bg:status", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/** Asks the daemon to stop the background server; refuses (ok:false) while any claim is live, naming the owners. */
|
|
664
|
+
export function bgStop(o: RtClientOptions = {}): Promise<RtResponse<Commands["bg:stop"]["data"]>> {
|
|
665
|
+
return rtCommand<Commands["bg:stop"]["data"]>("bg:stop", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
export function bgRelease(
|
|
669
|
+
a: Commands["bg:release"]["payload"],
|
|
670
|
+
o: RtClientOptions = {},
|
|
671
|
+
): Promise<RtResponse<Commands["bg:release"]["data"]>> {
|
|
672
|
+
return rtCommand<Commands["bg:release"]["data"]>("bg:release", { claim: a.claim }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
673
|
+
}
|