syntaur 0.1.2 → 0.1.4
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
CHANGED
|
@@ -114,3 +114,31 @@ Repo-local plugin linking for development:
|
|
|
114
114
|
npx syntaur@latest install-plugin --link
|
|
115
115
|
npx syntaur@latest install-codex-plugin --link
|
|
116
116
|
```
|
|
117
|
+
|
|
118
|
+
## Release Publishing
|
|
119
|
+
|
|
120
|
+
This repo is set up for npm trusted publishing from GitHub Actions.
|
|
121
|
+
|
|
122
|
+
Release flow:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm version patch
|
|
126
|
+
git push origin main
|
|
127
|
+
git push origin v$(node -p "require('./package.json').version")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The publish workflow lives at `.github/workflows/publish.yml` and only runs on version tags like `v0.1.4`. It checks that the tag matches `package.json`, runs the repo validation, and then publishes to npm using GitHub OIDC instead of a long-lived npm token.
|
|
131
|
+
|
|
132
|
+
One-time npm setup:
|
|
133
|
+
|
|
134
|
+
- package: `syntaur`
|
|
135
|
+
- GitHub repo: `prong-horn/syntaur`
|
|
136
|
+
- workflow filename: `publish.yml`
|
|
137
|
+
|
|
138
|
+
You can configure the trusted publisher either in the npm package settings UI or with npm CLI `11.10+`:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npx npm@^11.10.0 trust github syntaur --repo prong-horn/syntaur --file publish.yml -y
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
After trusted publishing is working, npm recommends switching the package publishing access to `Require two-factor authentication and disallow tokens`.
|
package/dist/index.js
CHANGED
|
@@ -4773,6 +4773,7 @@ Use --slug to specify a different slug.`
|
|
|
4773
4773
|
// src/commands/dashboard.ts
|
|
4774
4774
|
init_config2();
|
|
4775
4775
|
import { spawn } from "child_process";
|
|
4776
|
+
import { createServer as createNetServer } from "net";
|
|
4776
4777
|
import { resolve as resolve18, dirname as dirname5 } from "path";
|
|
4777
4778
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4778
4779
|
|
|
@@ -7234,6 +7235,30 @@ function resolveDashboardMode(options) {
|
|
|
7234
7235
|
}
|
|
7235
7236
|
return "static";
|
|
7236
7237
|
}
|
|
7238
|
+
async function isPortAvailable(port) {
|
|
7239
|
+
return new Promise((resolveAvailability) => {
|
|
7240
|
+
const tester = createNetServer();
|
|
7241
|
+
tester.once("error", () => {
|
|
7242
|
+
resolveAvailability(false);
|
|
7243
|
+
});
|
|
7244
|
+
tester.once("listening", () => {
|
|
7245
|
+
tester.close(() => resolveAvailability(true));
|
|
7246
|
+
});
|
|
7247
|
+
tester.listen(port, "127.0.0.1");
|
|
7248
|
+
});
|
|
7249
|
+
}
|
|
7250
|
+
async function findAvailablePort(startPort, maxAttempts = 20) {
|
|
7251
|
+
for (let offset = 0; offset < maxAttempts; offset += 1) {
|
|
7252
|
+
const candidate = startPort + offset;
|
|
7253
|
+
if (candidate > 65535) {
|
|
7254
|
+
break;
|
|
7255
|
+
}
|
|
7256
|
+
if (await isPortAvailable(candidate)) {
|
|
7257
|
+
return candidate;
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
return null;
|
|
7261
|
+
}
|
|
7237
7262
|
async function dashboardCommand(options) {
|
|
7238
7263
|
const config = await readConfig();
|
|
7239
7264
|
const missionsDir = config.defaultMissionDir;
|
|
@@ -8343,6 +8368,19 @@ import { createInterface } from "readline/promises";
|
|
|
8343
8368
|
function isInteractiveTerminal() {
|
|
8344
8369
|
return Boolean(input.isTTY && output.isTTY);
|
|
8345
8370
|
}
|
|
8371
|
+
function parseConfirmAnswer(answer, defaultValue = false) {
|
|
8372
|
+
const normalized = answer.trim().toLowerCase();
|
|
8373
|
+
if (normalized === "") {
|
|
8374
|
+
return defaultValue;
|
|
8375
|
+
}
|
|
8376
|
+
if (normalized === "y" || normalized === "yes") {
|
|
8377
|
+
return true;
|
|
8378
|
+
}
|
|
8379
|
+
if (normalized === "n" || normalized === "no") {
|
|
8380
|
+
return false;
|
|
8381
|
+
}
|
|
8382
|
+
return null;
|
|
8383
|
+
}
|
|
8346
8384
|
async function confirmPrompt(question, defaultValue = false) {
|
|
8347
8385
|
if (!isInteractiveTerminal()) {
|
|
8348
8386
|
throw new Error("Interactive confirmation requires a TTY.");
|
|
@@ -8350,11 +8388,14 @@ async function confirmPrompt(question, defaultValue = false) {
|
|
|
8350
8388
|
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
8351
8389
|
const rl = createInterface({ input, output });
|
|
8352
8390
|
try {
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8391
|
+
while (true) {
|
|
8392
|
+
const answer = await rl.question(`${question}${suffix}`);
|
|
8393
|
+
const parsed = parseConfirmAnswer(answer, defaultValue);
|
|
8394
|
+
if (parsed !== null) {
|
|
8395
|
+
return parsed;
|
|
8396
|
+
}
|
|
8397
|
+
console.log("Enter y, yes, n, no, or press Enter for the default.");
|
|
8356
8398
|
}
|
|
8357
|
-
return answer === "y" || answer === "yes";
|
|
8358
8399
|
} finally {
|
|
8359
8400
|
rl.close();
|
|
8360
8401
|
}
|
|
@@ -8591,7 +8632,7 @@ async function setupCommand(options) {
|
|
|
8591
8632
|
targetDir: options.claudeDir,
|
|
8592
8633
|
promptForTarget: !options.yes
|
|
8593
8634
|
});
|
|
8594
|
-
} else
|
|
8635
|
+
} else {
|
|
8595
8636
|
console.log(`Skip Claude plugin for now. Install later with: ${getPluginInstallCommand("claude")}`);
|
|
8596
8637
|
}
|
|
8597
8638
|
if (installCodex) {
|
|
@@ -8600,12 +8641,22 @@ async function setupCommand(options) {
|
|
|
8600
8641
|
marketplacePath: options.codexMarketplacePath,
|
|
8601
8642
|
promptForTarget: !options.yes
|
|
8602
8643
|
});
|
|
8603
|
-
} else
|
|
8644
|
+
} else {
|
|
8604
8645
|
console.log(`Skip Codex plugin for now. Install later with: ${getPluginInstallCommand("codex")}`);
|
|
8605
8646
|
}
|
|
8606
8647
|
if (launchDashboard) {
|
|
8648
|
+
const preferredPort = 4800;
|
|
8649
|
+
const port = await findAvailablePort(preferredPort);
|
|
8650
|
+
if (port === null) {
|
|
8651
|
+
throw new Error(
|
|
8652
|
+
`Could not find an available dashboard port starting at ${preferredPort}. Run "syntaur dashboard --port <number>" to choose one manually.`
|
|
8653
|
+
);
|
|
8654
|
+
}
|
|
8655
|
+
if (port !== preferredPort) {
|
|
8656
|
+
console.log(`Port ${preferredPort} is busy. Launching the dashboard on port ${port} instead.`);
|
|
8657
|
+
}
|
|
8607
8658
|
await dashboardCommand({
|
|
8608
|
-
port:
|
|
8659
|
+
port: String(port),
|
|
8609
8660
|
dev: false,
|
|
8610
8661
|
serverOnly: false,
|
|
8611
8662
|
apiOnly: false,
|