@hua-labs/tap 0.2.0 → 0.2.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/dist/bridges/codex-app-server-bridge.d.mts +55 -0
- package/dist/bridges/codex-app-server-bridge.mjs +1358 -0
- package/dist/bridges/codex-app-server-bridge.mjs.map +1 -0
- package/dist/bridges/codex-bridge-runner.d.mts +2 -1
- package/dist/bridges/codex-bridge-runner.mjs +41 -9
- package/dist/bridges/codex-bridge-runner.mjs.map +1 -1
- package/dist/cli.mjs +262 -19
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +32 -4
- package/dist/index.mjs +3512 -195
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/commands/init.ts
|
|
2
2
|
import * as fs6 from "fs";
|
|
3
3
|
import * as path6 from "path";
|
|
4
|
+
import { execSync } from "child_process";
|
|
4
5
|
|
|
5
6
|
// src/state.ts
|
|
6
7
|
import * as fs3 from "fs";
|
|
@@ -186,7 +187,7 @@ function loadJsonFile(filePath) {
|
|
|
186
187
|
return null;
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
|
-
function
|
|
190
|
+
function loadSharedConfig2(repoRoot) {
|
|
190
191
|
return loadJsonFile(path2.join(repoRoot, SHARED_CONFIG_FILE));
|
|
191
192
|
}
|
|
192
193
|
function loadLocalConfig(repoRoot) {
|
|
@@ -210,7 +211,7 @@ function loadLegacyShellConfig(repoRoot) {
|
|
|
210
211
|
}
|
|
211
212
|
function resolveConfig(overrides = {}, startDir) {
|
|
212
213
|
const repoRoot = findRepoRoot2(startDir);
|
|
213
|
-
const shared =
|
|
214
|
+
const shared = loadSharedConfig2(repoRoot) ?? {};
|
|
214
215
|
const local = loadLocalConfig(repoRoot) ?? {};
|
|
215
216
|
const legacy = loadLegacyShellConfig(repoRoot) ?? {};
|
|
216
217
|
const sources = {
|
|
@@ -292,6 +293,12 @@ function resolveConfig(overrides = {}, startDir) {
|
|
|
292
293
|
sources
|
|
293
294
|
};
|
|
294
295
|
}
|
|
296
|
+
function saveSharedConfig(repoRoot, config) {
|
|
297
|
+
const filePath = path2.join(repoRoot, SHARED_CONFIG_FILE);
|
|
298
|
+
const tmp = `${filePath}.tmp.${process.pid}`;
|
|
299
|
+
fs2.writeFileSync(tmp, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
300
|
+
fs2.renameSync(tmp, filePath);
|
|
301
|
+
}
|
|
295
302
|
function resolvePath(repoRoot, p) {
|
|
296
303
|
const normalized = normalizeTapPath(p);
|
|
297
304
|
return path2.isAbsolute(normalized) ? normalized : path2.resolve(repoRoot, normalized);
|
|
@@ -753,6 +760,64 @@ async function initCommand(args) {
|
|
|
753
760
|
};
|
|
754
761
|
}
|
|
755
762
|
logHeader("@hua-labs/tap init");
|
|
763
|
+
const commsRepoIdx = args.indexOf("--comms-repo");
|
|
764
|
+
const commsRepoUrl = commsRepoIdx !== -1 && args[commsRepoIdx + 1] ? args[commsRepoIdx + 1] : void 0;
|
|
765
|
+
if (commsRepoUrl) {
|
|
766
|
+
if (fs6.existsSync(commsDir) && fs6.readdirSync(commsDir).length > 0) {
|
|
767
|
+
const gitDir = path6.join(commsDir, ".git");
|
|
768
|
+
if (fs6.existsSync(gitDir)) {
|
|
769
|
+
log(`Comms directory exists: ${commsDir}`);
|
|
770
|
+
logSuccess("Comms directory is already a git repo \u2014 linking only");
|
|
771
|
+
} else {
|
|
772
|
+
logError(`Comms directory exists but is not a git repo: ${commsDir}`);
|
|
773
|
+
return {
|
|
774
|
+
ok: false,
|
|
775
|
+
command: "init",
|
|
776
|
+
code: "TAP_INIT_CLONE_FAILED",
|
|
777
|
+
message: `Comms directory "${commsDir}" exists but is not a git repo. Remove it or use --force to reinitialize.`,
|
|
778
|
+
warnings: [],
|
|
779
|
+
data: { commsDir, commsRepoUrl }
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
} else {
|
|
783
|
+
log(`Cloning comms repo: ${commsRepoUrl}`);
|
|
784
|
+
try {
|
|
785
|
+
execSync(`git clone "${commsRepoUrl}" "${commsDir}"`, {
|
|
786
|
+
stdio: "pipe",
|
|
787
|
+
encoding: "utf-8"
|
|
788
|
+
});
|
|
789
|
+
logSuccess(`Cloned comms repo to ${commsDir}`);
|
|
790
|
+
} catch (err) {
|
|
791
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
792
|
+
logError(`Failed to clone comms repo: ${msg}`);
|
|
793
|
+
return {
|
|
794
|
+
ok: false,
|
|
795
|
+
command: "init",
|
|
796
|
+
code: "TAP_INIT_CLONE_FAILED",
|
|
797
|
+
message: `Failed to clone comms repo: ${msg}`,
|
|
798
|
+
warnings: [],
|
|
799
|
+
data: { commsRepoUrl }
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
{
|
|
805
|
+
const sharedConfig = loadSharedConfig2(repoRoot) ?? {};
|
|
806
|
+
let configChanged = false;
|
|
807
|
+
if (commsRepoUrl) {
|
|
808
|
+
sharedConfig.commsRepoUrl = commsRepoUrl;
|
|
809
|
+
configChanged = true;
|
|
810
|
+
}
|
|
811
|
+
const commsDirRelative = path6.relative(repoRoot, commsDir);
|
|
812
|
+
if (commsDirRelative && commsDirRelative !== "tap-comms") {
|
|
813
|
+
sharedConfig.commsDir = commsDirRelative;
|
|
814
|
+
configChanged = true;
|
|
815
|
+
}
|
|
816
|
+
if (configChanged) {
|
|
817
|
+
saveSharedConfig(repoRoot, sharedConfig);
|
|
818
|
+
logSuccess("Saved comms config to tap-config.json");
|
|
819
|
+
}
|
|
820
|
+
}
|
|
756
821
|
log(`Comms directory: ${commsDir}`);
|
|
757
822
|
for (const dir of COMMS_DIRS) {
|
|
758
823
|
const dirPath = path6.join(commsDir, dir);
|
|
@@ -829,7 +894,7 @@ ${entry}
|
|
|
829
894
|
// src/adapters/claude.ts
|
|
830
895
|
import * as fs8 from "fs";
|
|
831
896
|
import * as path8 from "path";
|
|
832
|
-
import { execSync } from "child_process";
|
|
897
|
+
import { execSync as execSync2 } from "child_process";
|
|
833
898
|
|
|
834
899
|
// src/adapters/common.ts
|
|
835
900
|
import * as fs7 from "fs";
|
|
@@ -972,7 +1037,7 @@ function findMcpJsonPath(ctx) {
|
|
|
972
1037
|
}
|
|
973
1038
|
function findClaudeCommand() {
|
|
974
1039
|
try {
|
|
975
|
-
|
|
1040
|
+
execSync2("claude --version", { stdio: "pipe" });
|
|
976
1041
|
return "claude";
|
|
977
1042
|
} catch {
|
|
978
1043
|
return null;
|
|
@@ -1834,13 +1899,13 @@ import * as fs13 from "fs";
|
|
|
1834
1899
|
import * as net from "net";
|
|
1835
1900
|
import * as path13 from "path";
|
|
1836
1901
|
import { randomBytes } from "crypto";
|
|
1837
|
-
import { spawn, spawnSync as spawnSync2, execSync as
|
|
1902
|
+
import { spawn, spawnSync as spawnSync2, execSync as execSync4 } from "child_process";
|
|
1838
1903
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1839
1904
|
|
|
1840
1905
|
// src/runtime/resolve-node.ts
|
|
1841
1906
|
import * as fs12 from "fs";
|
|
1842
1907
|
import * as path12 from "path";
|
|
1843
|
-
import { execSync as
|
|
1908
|
+
import { execSync as execSync3 } from "child_process";
|
|
1844
1909
|
function readNodeVersion(repoRoot) {
|
|
1845
1910
|
const nvFile = path12.join(repoRoot, ".node-version");
|
|
1846
1911
|
if (!fs12.existsSync(nvFile)) return null;
|
|
@@ -1883,7 +1948,7 @@ function probeFnmNode(desiredVersion) {
|
|
|
1883
1948
|
);
|
|
1884
1949
|
if (!fs12.existsSync(candidate)) continue;
|
|
1885
1950
|
try {
|
|
1886
|
-
const v =
|
|
1951
|
+
const v = execSync3(`"${candidate}" --version`, {
|
|
1887
1952
|
encoding: "utf-8",
|
|
1888
1953
|
timeout: 5e3
|
|
1889
1954
|
}).trim();
|
|
@@ -1897,7 +1962,7 @@ function probeFnmNode(desiredVersion) {
|
|
|
1897
1962
|
}
|
|
1898
1963
|
function detectNodeMajorVersion(command) {
|
|
1899
1964
|
try {
|
|
1900
|
-
const version2 =
|
|
1965
|
+
const version2 = execSync3(`"${command}" --version`, {
|
|
1901
1966
|
encoding: "utf-8",
|
|
1902
1967
|
timeout: 5e3
|
|
1903
1968
|
}).trim();
|
|
@@ -1911,7 +1976,7 @@ function checkStripTypesSupport(command) {
|
|
|
1911
1976
|
const major = detectNodeMajorVersion(command);
|
|
1912
1977
|
if (major !== null && major >= 22) return true;
|
|
1913
1978
|
try {
|
|
1914
|
-
|
|
1979
|
+
execSync3(`"${command}" --experimental-strip-types -e ""`, {
|
|
1915
1980
|
timeout: 5e3,
|
|
1916
1981
|
stdio: "pipe"
|
|
1917
1982
|
});
|
|
@@ -2469,7 +2534,7 @@ async function terminateProcess(pid, platform) {
|
|
|
2469
2534
|
}
|
|
2470
2535
|
try {
|
|
2471
2536
|
if (platform === "win32") {
|
|
2472
|
-
|
|
2537
|
+
execSync4(`taskkill /PID ${pid} /F /T`, { stdio: "pipe" });
|
|
2473
2538
|
} else {
|
|
2474
2539
|
process.kill(pid, "SIGTERM");
|
|
2475
2540
|
await delay(2e3);
|
|
@@ -4543,7 +4608,7 @@ async function bridgeCommand(args) {
|
|
|
4543
4608
|
// src/engine/dashboard.ts
|
|
4544
4609
|
import * as fs15 from "fs";
|
|
4545
4610
|
import * as path15 from "path";
|
|
4546
|
-
import { execSync as
|
|
4611
|
+
import { execSync as execSync5 } from "child_process";
|
|
4547
4612
|
function collectAgents(commsDir) {
|
|
4548
4613
|
const heartbeatsPath = path15.join(commsDir, "heartbeats.json");
|
|
4549
4614
|
if (!fs15.existsSync(heartbeatsPath)) return [];
|
|
@@ -4622,7 +4687,7 @@ function collectBridges(repoRoot) {
|
|
|
4622
4687
|
}
|
|
4623
4688
|
function collectPRs() {
|
|
4624
4689
|
try {
|
|
4625
|
-
const output =
|
|
4690
|
+
const output = execSync5(
|
|
4626
4691
|
"gh pr list --state all --limit 10 --json number,title,author,state,url",
|
|
4627
4692
|
{ encoding: "utf-8", timeout: 1e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
4628
4693
|
);
|
|
@@ -4869,7 +4934,7 @@ async function serveCommand(args) {
|
|
|
4869
4934
|
// src/commands/init-worktree.ts
|
|
4870
4935
|
import * as fs16 from "fs";
|
|
4871
4936
|
import * as path17 from "path";
|
|
4872
|
-
import { execSync as
|
|
4937
|
+
import { execSync as execSync6 } from "child_process";
|
|
4873
4938
|
var INIT_WORKTREE_HELP = `
|
|
4874
4939
|
Usage:
|
|
4875
4940
|
tap-comms init-worktree [options]
|
|
@@ -4893,7 +4958,7 @@ function warn(warnings, message) {
|
|
|
4893
4958
|
}
|
|
4894
4959
|
function run(cmd, opts) {
|
|
4895
4960
|
try {
|
|
4896
|
-
return
|
|
4961
|
+
return execSync6(cmd, {
|
|
4897
4962
|
cwd: opts?.cwd,
|
|
4898
4963
|
encoding: "utf-8",
|
|
4899
4964
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -4910,7 +4975,7 @@ function toAbsolute(p) {
|
|
|
4910
4975
|
}
|
|
4911
4976
|
function probeBun(candidate) {
|
|
4912
4977
|
try {
|
|
4913
|
-
const out =
|
|
4978
|
+
const out = execSync6(`"${candidate}" --version`, {
|
|
4914
4979
|
encoding: "utf-8",
|
|
4915
4980
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4916
4981
|
timeout: 5e3
|
|
@@ -4924,7 +4989,7 @@ function findBun() {
|
|
|
4924
4989
|
const candidates = process.platform === "win32" ? ["bun.exe", "bun"] : ["bun"];
|
|
4925
4990
|
for (const name of candidates) {
|
|
4926
4991
|
try {
|
|
4927
|
-
const out =
|
|
4992
|
+
const out = execSync6(
|
|
4928
4993
|
process.platform === "win32" ? `where ${name}` : `which ${name}`,
|
|
4929
4994
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 }
|
|
4930
4995
|
).trim();
|
|
@@ -5376,7 +5441,7 @@ async function dashboardCommand(args) {
|
|
|
5376
5441
|
import {
|
|
5377
5442
|
existsSync as existsSync16,
|
|
5378
5443
|
mkdirSync as mkdirSync10,
|
|
5379
|
-
readdirSync as
|
|
5444
|
+
readdirSync as readdirSync4,
|
|
5380
5445
|
readFileSync as readFileSync14,
|
|
5381
5446
|
statSync as statSync2,
|
|
5382
5447
|
unlinkSync as unlinkSync3
|
|
@@ -5388,7 +5453,7 @@ var FAIL = "fail";
|
|
|
5388
5453
|
function countFiles(dir, ext = ".md") {
|
|
5389
5454
|
if (!existsSync16(dir)) return 0;
|
|
5390
5455
|
try {
|
|
5391
|
-
return
|
|
5456
|
+
return readdirSync4(dir).filter((f) => f.endsWith(ext)).length;
|
|
5392
5457
|
} catch {
|
|
5393
5458
|
return 0;
|
|
5394
5459
|
}
|
|
@@ -5398,7 +5463,7 @@ function recentFileCount(dir, withinMs) {
|
|
|
5398
5463
|
const cutoff = Date.now() - withinMs;
|
|
5399
5464
|
let count = 0;
|
|
5400
5465
|
try {
|
|
5401
|
-
for (const f of
|
|
5466
|
+
for (const f of readdirSync4(dir)) {
|
|
5402
5467
|
if (!f.endsWith(".md")) continue;
|
|
5403
5468
|
try {
|
|
5404
5469
|
if (statSync2(join17(dir, f)).mtimeMs > cutoff) count++;
|
|
@@ -5409,6 +5474,21 @@ function recentFileCount(dir, withinMs) {
|
|
|
5409
5474
|
}
|
|
5410
5475
|
return count;
|
|
5411
5476
|
}
|
|
5477
|
+
function loadBridgeRuntimeHeartbeat(bridgeState) {
|
|
5478
|
+
const runtimeStateDir = bridgeState?.runtimeStateDir;
|
|
5479
|
+
if (!runtimeStateDir) {
|
|
5480
|
+
return null;
|
|
5481
|
+
}
|
|
5482
|
+
const heartbeatPath = join17(runtimeStateDir, "heartbeat.json");
|
|
5483
|
+
if (!existsSync16(heartbeatPath)) {
|
|
5484
|
+
return null;
|
|
5485
|
+
}
|
|
5486
|
+
try {
|
|
5487
|
+
return JSON.parse(readFileSync14(heartbeatPath, "utf-8"));
|
|
5488
|
+
} catch {
|
|
5489
|
+
return null;
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5412
5492
|
function checkComms(commsDir) {
|
|
5413
5493
|
const checks = [];
|
|
5414
5494
|
checks.push({
|
|
@@ -5492,6 +5572,7 @@ function checkInstances(repoRoot, stateDir) {
|
|
|
5492
5572
|
const running = isBridgeRunning(stateDir, id);
|
|
5493
5573
|
const bridgeState = loadBridgeState(stateDir, id);
|
|
5494
5574
|
const heartbeatAge = getHeartbeatAge(stateDir, id);
|
|
5575
|
+
const runtimeHeartbeat = loadBridgeRuntimeHeartbeat(bridgeState);
|
|
5495
5576
|
let status;
|
|
5496
5577
|
let message;
|
|
5497
5578
|
let fix;
|
|
@@ -5535,6 +5616,11 @@ function checkInstances(repoRoot, stateDir) {
|
|
|
5535
5616
|
status = WARN;
|
|
5536
5617
|
message = "Not running";
|
|
5537
5618
|
}
|
|
5619
|
+
const lastRuntimeError = runtimeHeartbeat?.lastError?.trim();
|
|
5620
|
+
if (lastRuntimeError) {
|
|
5621
|
+
status = status === FAIL ? FAIL : WARN;
|
|
5622
|
+
message = `${message}; bridge last error: ${lastRuntimeError}`;
|
|
5623
|
+
}
|
|
5538
5624
|
checks.push({ name: `bridge: ${id}`, status, message, fix });
|
|
5539
5625
|
} else {
|
|
5540
5626
|
checks.push({
|
|
@@ -5737,6 +5823,158 @@ async function doctorCommand(args) {
|
|
|
5737
5823
|
};
|
|
5738
5824
|
}
|
|
5739
5825
|
|
|
5826
|
+
// src/commands/comms.ts
|
|
5827
|
+
import { execSync as execSync7 } from "child_process";
|
|
5828
|
+
import * as fs17 from "fs";
|
|
5829
|
+
import * as path18 from "path";
|
|
5830
|
+
var COMMS_HELP = `
|
|
5831
|
+
Usage:
|
|
5832
|
+
tap-comms comms <subcommand>
|
|
5833
|
+
|
|
5834
|
+
Subcommands:
|
|
5835
|
+
pull Pull latest changes from comms remote repo
|
|
5836
|
+
push Commit and push comms changes to remote repo
|
|
5837
|
+
|
|
5838
|
+
Examples:
|
|
5839
|
+
npx @hua-labs/tap comms pull
|
|
5840
|
+
npx @hua-labs/tap comms push
|
|
5841
|
+
`.trim();
|
|
5842
|
+
function isGitRepo(dir) {
|
|
5843
|
+
return fs17.existsSync(path18.join(dir, ".git"));
|
|
5844
|
+
}
|
|
5845
|
+
function commsPull(commsDir) {
|
|
5846
|
+
logHeader("tap comms pull");
|
|
5847
|
+
if (!isGitRepo(commsDir)) {
|
|
5848
|
+
logError(`${commsDir} is not a git repository`);
|
|
5849
|
+
return {
|
|
5850
|
+
ok: false,
|
|
5851
|
+
command: "comms",
|
|
5852
|
+
code: "TAP_COMMS_NOT_REPO",
|
|
5853
|
+
message: `Comms directory is not a git repo. Use 'tap init --comms-repo <url>' to set up.`,
|
|
5854
|
+
warnings: [],
|
|
5855
|
+
data: { commsDir }
|
|
5856
|
+
};
|
|
5857
|
+
}
|
|
5858
|
+
try {
|
|
5859
|
+
const output = execSync7("git pull --rebase", {
|
|
5860
|
+
cwd: commsDir,
|
|
5861
|
+
encoding: "utf-8",
|
|
5862
|
+
stdio: "pipe"
|
|
5863
|
+
});
|
|
5864
|
+
logSuccess("Comms pull complete");
|
|
5865
|
+
if (output.trim()) log(output.trim());
|
|
5866
|
+
return {
|
|
5867
|
+
ok: true,
|
|
5868
|
+
command: "comms",
|
|
5869
|
+
code: "TAP_COMMS_PULL_OK",
|
|
5870
|
+
message: "Comms pull complete",
|
|
5871
|
+
warnings: [],
|
|
5872
|
+
data: { commsDir }
|
|
5873
|
+
};
|
|
5874
|
+
} catch (err) {
|
|
5875
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5876
|
+
logError(`Pull failed: ${msg}`);
|
|
5877
|
+
return {
|
|
5878
|
+
ok: false,
|
|
5879
|
+
command: "comms",
|
|
5880
|
+
code: "TAP_COMMS_PULL_FAILED",
|
|
5881
|
+
message: `Pull failed: ${msg}`,
|
|
5882
|
+
warnings: [],
|
|
5883
|
+
data: { commsDir }
|
|
5884
|
+
};
|
|
5885
|
+
}
|
|
5886
|
+
}
|
|
5887
|
+
function commsPush(commsDir) {
|
|
5888
|
+
logHeader("tap comms push");
|
|
5889
|
+
if (!isGitRepo(commsDir)) {
|
|
5890
|
+
logError(`${commsDir} is not a git repository`);
|
|
5891
|
+
return {
|
|
5892
|
+
ok: false,
|
|
5893
|
+
command: "comms",
|
|
5894
|
+
code: "TAP_COMMS_NOT_REPO",
|
|
5895
|
+
message: `Comms directory is not a git repo. Use 'tap init --comms-repo <url>' to set up.`,
|
|
5896
|
+
warnings: [],
|
|
5897
|
+
data: { commsDir }
|
|
5898
|
+
};
|
|
5899
|
+
}
|
|
5900
|
+
try {
|
|
5901
|
+
execSync7("git add -A", { cwd: commsDir, stdio: "pipe" });
|
|
5902
|
+
const status = execSync7("git status --porcelain", {
|
|
5903
|
+
cwd: commsDir,
|
|
5904
|
+
encoding: "utf-8",
|
|
5905
|
+
stdio: "pipe"
|
|
5906
|
+
}).trim();
|
|
5907
|
+
if (!status) {
|
|
5908
|
+
log("Nothing to push \u2014 comms directory is clean");
|
|
5909
|
+
return {
|
|
5910
|
+
ok: true,
|
|
5911
|
+
command: "comms",
|
|
5912
|
+
code: "TAP_COMMS_PUSH_OK",
|
|
5913
|
+
message: "Nothing to push",
|
|
5914
|
+
warnings: [],
|
|
5915
|
+
data: { commsDir, changed: false }
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
5919
|
+
execSync7(`git commit -m "chore(comms): sync ${timestamp}"`, {
|
|
5920
|
+
cwd: commsDir,
|
|
5921
|
+
stdio: "pipe"
|
|
5922
|
+
});
|
|
5923
|
+
execSync7("git push", { cwd: commsDir, stdio: "pipe" });
|
|
5924
|
+
logSuccess("Comms push complete");
|
|
5925
|
+
return {
|
|
5926
|
+
ok: true,
|
|
5927
|
+
command: "comms",
|
|
5928
|
+
code: "TAP_COMMS_PUSH_OK",
|
|
5929
|
+
message: "Comms push complete",
|
|
5930
|
+
warnings: [],
|
|
5931
|
+
data: { commsDir, changed: true }
|
|
5932
|
+
};
|
|
5933
|
+
} catch (err) {
|
|
5934
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5935
|
+
logError(`Push failed: ${msg}`);
|
|
5936
|
+
return {
|
|
5937
|
+
ok: false,
|
|
5938
|
+
command: "comms",
|
|
5939
|
+
code: "TAP_COMMS_PUSH_FAILED",
|
|
5940
|
+
message: `Push failed: ${msg}`,
|
|
5941
|
+
warnings: [],
|
|
5942
|
+
data: { commsDir }
|
|
5943
|
+
};
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
async function commsCommand(args) {
|
|
5947
|
+
const subcommand = args[0];
|
|
5948
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
5949
|
+
log(COMMS_HELP);
|
|
5950
|
+
return {
|
|
5951
|
+
ok: true,
|
|
5952
|
+
command: "comms",
|
|
5953
|
+
code: "TAP_NO_OP",
|
|
5954
|
+
message: COMMS_HELP,
|
|
5955
|
+
warnings: [],
|
|
5956
|
+
data: {}
|
|
5957
|
+
};
|
|
5958
|
+
}
|
|
5959
|
+
const repoRoot = findRepoRoot();
|
|
5960
|
+
const commsDir = resolveCommsDir(args, repoRoot);
|
|
5961
|
+
switch (subcommand) {
|
|
5962
|
+
case "pull":
|
|
5963
|
+
return commsPull(commsDir);
|
|
5964
|
+
case "push":
|
|
5965
|
+
return commsPush(commsDir);
|
|
5966
|
+
default:
|
|
5967
|
+
return {
|
|
5968
|
+
ok: false,
|
|
5969
|
+
command: "comms",
|
|
5970
|
+
code: "TAP_INVALID_ARGUMENT",
|
|
5971
|
+
message: `Unknown comms subcommand: ${subcommand}. Use pull or push.`,
|
|
5972
|
+
warnings: [],
|
|
5973
|
+
data: {}
|
|
5974
|
+
};
|
|
5975
|
+
}
|
|
5976
|
+
}
|
|
5977
|
+
|
|
5740
5978
|
// src/output.ts
|
|
5741
5979
|
function emitResult(result, jsonMode) {
|
|
5742
5980
|
if (jsonMode) {
|
|
@@ -5777,6 +6015,7 @@ Commands:
|
|
|
5777
6015
|
bridge <sub> [inst] Manage bridges (start, stop, status)
|
|
5778
6016
|
up Start all registered bridge daemons
|
|
5779
6017
|
down Stop all running bridge daemons
|
|
6018
|
+
comms <pull|push> Sync comms directory with remote repo
|
|
5780
6019
|
dashboard Show unified ops dashboard
|
|
5781
6020
|
doctor Diagnose tap infrastructure health
|
|
5782
6021
|
serve Start tap-comms MCP server (stdio)
|
|
@@ -5804,6 +6043,7 @@ function normalizeCommandName(command) {
|
|
|
5804
6043
|
case "bridge":
|
|
5805
6044
|
case "up":
|
|
5806
6045
|
case "down":
|
|
6046
|
+
case "comms":
|
|
5807
6047
|
case "dashboard":
|
|
5808
6048
|
case "doctor":
|
|
5809
6049
|
case "serve":
|
|
@@ -5861,6 +6101,9 @@ async function main() {
|
|
|
5861
6101
|
case "down":
|
|
5862
6102
|
result = await downCommand(commandArgs);
|
|
5863
6103
|
break;
|
|
6104
|
+
case "comms":
|
|
6105
|
+
result = await commsCommand(commandArgs);
|
|
6106
|
+
break;
|
|
5864
6107
|
case "dashboard":
|
|
5865
6108
|
result = await dashboardCommand(commandArgs);
|
|
5866
6109
|
break;
|