syntaur 0.1.2 → 0.1.5
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 +28 -0
- package/dist/index.js +79 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugins/syntaur/.codex-plugin/plugin.json +1 -1
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,14 +7235,51 @@ 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;
|
|
7240
|
-
const
|
|
7241
|
-
if (isNaN(
|
|
7265
|
+
const requestedPort = parseInt(options.port, 10);
|
|
7266
|
+
if (isNaN(requestedPort) || requestedPort < 1 || requestedPort > 65535) {
|
|
7242
7267
|
throw new Error(`Invalid port "${options.port}". Must be a number between 1 and 65535.`);
|
|
7243
7268
|
}
|
|
7244
7269
|
const mode = resolveDashboardMode(options);
|
|
7270
|
+
let port = requestedPort;
|
|
7271
|
+
if (options.autoPort) {
|
|
7272
|
+
const availablePort = await findAvailablePort(requestedPort);
|
|
7273
|
+
if (availablePort === null) {
|
|
7274
|
+
throw new Error(
|
|
7275
|
+
`Could not find an available dashboard port starting at ${requestedPort}. Run "syntaur dashboard --port <number>" to choose one manually.`
|
|
7276
|
+
);
|
|
7277
|
+
}
|
|
7278
|
+
if (availablePort !== requestedPort) {
|
|
7279
|
+
console.log(`Port ${requestedPort} is busy. Launching the dashboard on port ${availablePort} instead.`);
|
|
7280
|
+
}
|
|
7281
|
+
port = availablePort;
|
|
7282
|
+
}
|
|
7245
7283
|
const server = createDashboardServer({
|
|
7246
7284
|
port,
|
|
7247
7285
|
missionsDir,
|
|
@@ -8343,6 +8381,19 @@ import { createInterface } from "readline/promises";
|
|
|
8343
8381
|
function isInteractiveTerminal() {
|
|
8344
8382
|
return Boolean(input.isTTY && output.isTTY);
|
|
8345
8383
|
}
|
|
8384
|
+
function parseConfirmAnswer(answer, defaultValue = false) {
|
|
8385
|
+
const normalized = answer.trim().toLowerCase();
|
|
8386
|
+
if (normalized === "") {
|
|
8387
|
+
return defaultValue;
|
|
8388
|
+
}
|
|
8389
|
+
if (normalized === "y" || normalized === "yes") {
|
|
8390
|
+
return true;
|
|
8391
|
+
}
|
|
8392
|
+
if (normalized === "n" || normalized === "no") {
|
|
8393
|
+
return false;
|
|
8394
|
+
}
|
|
8395
|
+
return null;
|
|
8396
|
+
}
|
|
8346
8397
|
async function confirmPrompt(question, defaultValue = false) {
|
|
8347
8398
|
if (!isInteractiveTerminal()) {
|
|
8348
8399
|
throw new Error("Interactive confirmation requires a TTY.");
|
|
@@ -8350,11 +8401,14 @@ async function confirmPrompt(question, defaultValue = false) {
|
|
|
8350
8401
|
const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
|
|
8351
8402
|
const rl = createInterface({ input, output });
|
|
8352
8403
|
try {
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8404
|
+
while (true) {
|
|
8405
|
+
const answer = await rl.question(`${question}${suffix}`);
|
|
8406
|
+
const parsed = parseConfirmAnswer(answer, defaultValue);
|
|
8407
|
+
if (parsed !== null) {
|
|
8408
|
+
return parsed;
|
|
8409
|
+
}
|
|
8410
|
+
console.log("Enter y, yes, n, no, or press Enter for the default.");
|
|
8356
8411
|
}
|
|
8357
|
-
return answer === "y" || answer === "yes";
|
|
8358
8412
|
} finally {
|
|
8359
8413
|
rl.close();
|
|
8360
8414
|
}
|
|
@@ -8591,7 +8645,7 @@ async function setupCommand(options) {
|
|
|
8591
8645
|
targetDir: options.claudeDir,
|
|
8592
8646
|
promptForTarget: !options.yes
|
|
8593
8647
|
});
|
|
8594
|
-
} else
|
|
8648
|
+
} else {
|
|
8595
8649
|
console.log(`Skip Claude plugin for now. Install later with: ${getPluginInstallCommand("claude")}`);
|
|
8596
8650
|
}
|
|
8597
8651
|
if (installCodex) {
|
|
@@ -8600,12 +8654,22 @@ async function setupCommand(options) {
|
|
|
8600
8654
|
marketplacePath: options.codexMarketplacePath,
|
|
8601
8655
|
promptForTarget: !options.yes
|
|
8602
8656
|
});
|
|
8603
|
-
} else
|
|
8657
|
+
} else {
|
|
8604
8658
|
console.log(`Skip Codex plugin for now. Install later with: ${getPluginInstallCommand("codex")}`);
|
|
8605
8659
|
}
|
|
8606
8660
|
if (launchDashboard) {
|
|
8661
|
+
const preferredPort = 4800;
|
|
8662
|
+
const port = await findAvailablePort(preferredPort);
|
|
8663
|
+
if (port === null) {
|
|
8664
|
+
throw new Error(
|
|
8665
|
+
`Could not find an available dashboard port starting at ${preferredPort}. Run "syntaur dashboard --port <number>" to choose one manually.`
|
|
8666
|
+
);
|
|
8667
|
+
}
|
|
8668
|
+
if (port !== preferredPort) {
|
|
8669
|
+
console.log(`Port ${preferredPort} is busy. Launching the dashboard on port ${port} instead.`);
|
|
8670
|
+
}
|
|
8607
8671
|
await dashboardCommand({
|
|
8608
|
-
port:
|
|
8672
|
+
port: String(port),
|
|
8609
8673
|
dev: false,
|
|
8610
8674
|
serverOnly: false,
|
|
8611
8675
|
apiOnly: false,
|
|
@@ -9384,9 +9448,13 @@ program.command("create-assignment").description("Create a new assignment within
|
|
|
9384
9448
|
process.exit(1);
|
|
9385
9449
|
}
|
|
9386
9450
|
});
|
|
9387
|
-
program.command("dashboard").description("Start the local Syntaur dashboard web UI").option("--port <number>", "Port to run the dashboard on", "4800").option("--dev", "Run the dashboard with the Vite dev server", false).option("--server-only", "Run only the API server without any UI", false).option("--api-only", "Deprecated alias for --server-only", false).option("--no-open", "Do not automatically open the browser").action(async (options) => {
|
|
9451
|
+
program.command("dashboard").description("Start the local Syntaur dashboard web UI").option("--port <number>", "Port to run the dashboard on", "4800").option("--dev", "Run the dashboard with the Vite dev server", false).option("--server-only", "Run only the API server without any UI", false).option("--api-only", "Deprecated alias for --server-only", false).option("--no-open", "Do not automatically open the browser").action(async (options, command) => {
|
|
9388
9452
|
try {
|
|
9389
|
-
|
|
9453
|
+
const autoPort = command.getOptionValueSource("port") !== "cli";
|
|
9454
|
+
await dashboardCommand({
|
|
9455
|
+
...options,
|
|
9456
|
+
autoPort
|
|
9457
|
+
});
|
|
9390
9458
|
} catch (error) {
|
|
9391
9459
|
console.error(
|
|
9392
9460
|
"Error:",
|