@tokenoftrust/cli 2.4.5 → 2.4.7
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/package.json +1 -1
- package/src/commands/submit.mjs +15 -10
- package/src/update-check.mjs +10 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.7",
|
|
4
4
|
"description": "Token of Trust developer CLI — clone a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Token of Trust",
|
package/src/commands/submit.mjs
CHANGED
|
@@ -1101,16 +1101,13 @@ export async function submitCandidate(scoped, { repo, changeId, ref, headSha, ch
|
|
|
1101
1101
|
return result;
|
|
1102
1102
|
} catch (e) {
|
|
1103
1103
|
if (e instanceof CandidateRegistrationError) throw e;
|
|
1104
|
-
//
|
|
1105
|
-
//
|
|
1106
|
-
//
|
|
1107
|
-
//
|
|
1108
|
-
//
|
|
1109
|
-
//
|
|
1110
|
-
|
|
1111
|
-
// registration failure) falls through to the original fatal error, unchanged.
|
|
1112
|
-
const httpStatus = /** @type {any} */ (e)?.diagnostic?.httpStatus;
|
|
1113
|
-
if (typeof httpStatus === "number" && httpStatus >= 500) {
|
|
1104
|
+
// candidate_open's forge write is idempotent and may have LANDED even though its
|
|
1105
|
+
// response never reached us (a gateway 5xx, a dropped connection, our own timeout).
|
|
1106
|
+
// Before reporting a fatal "candidate not created," re-read it by its stable changeId
|
|
1107
|
+
// — if it's already there with the exact ref/head we just pushed, this submit DID
|
|
1108
|
+
// succeed. Any error from the re-read (including "not found," the ordinary case for a
|
|
1109
|
+
// genuine registration failure) falls through to the original fatal error, unchanged.
|
|
1110
|
+
if (responseLost(e)) {
|
|
1114
1111
|
const existing = await fetchCandidateStatus(scoped, { repo, changeId }).catch(() => null);
|
|
1115
1112
|
if (
|
|
1116
1113
|
existing
|
|
@@ -1127,6 +1124,14 @@ export async function submitCandidate(scoped, { repo, changeId, ref, headSha, ch
|
|
|
1127
1124
|
}
|
|
1128
1125
|
}
|
|
1129
1126
|
|
|
1127
|
+
/** True when a call's outcome is unknown — the server may have acted, but its answer
|
|
1128
|
+
* never arrived — as opposed to a refusal the server actually sent. */
|
|
1129
|
+
function responseLost(error) {
|
|
1130
|
+
const d = /** @type {any} */ (error)?.diagnostic;
|
|
1131
|
+
if (typeof d?.httpStatus === "number" && d.httpStatus >= 500) return true;
|
|
1132
|
+
return d?.category === "network" || d?.category === "timeout";
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1130
1135
|
/** Print the candidate_open result: the PR the approver reviews, or the MCP's own
|
|
1131
1136
|
* refusal message when it couldn't open/update one. `quiet` (--json) suppresses it.
|
|
1132
1137
|
* Deliberately does NOT print `result.url` — that's the INTERNAL forge (Gitea) PR
|
package/src/update-check.mjs
CHANGED
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
* result (instant, no network on the hot path); the registry refresh happens in a
|
|
22
22
|
* DETACHED, unref'd child so it can't add latency or hold the process open.
|
|
23
23
|
* • Cached in `~/.tot/update-check.json`; refreshed at most once per CHECK_INTERVAL_MS.
|
|
24
|
-
* •
|
|
25
|
-
* NO_UPDATE_NOTIFIER is set. `TOT_HOME` overrides the home dir (tests).
|
|
24
|
+
* • Printed to stderr whether or not it is a TTY; suppressed in CI or when
|
|
25
|
+
* TOT_NO_UPDATE_CHECK / NO_UPDATE_NOTIFIER is set. `TOT_HOME` overrides the home dir (tests).
|
|
26
26
|
*/
|
|
27
27
|
import { readFileSync, writeFileSync, mkdirSync, renameSync, chmodSync } from "node:fs";
|
|
28
28
|
import { homedir } from "node:os";
|
|
@@ -195,11 +195,15 @@ export function renderNotice(notice, current) {
|
|
|
195
195
|
.join("\n");
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
/**
|
|
199
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Whether we should print a nudge at all in this environment. Deliberately NOT
|
|
200
|
+
* gated on a TTY: agent-driven sessions run `tot` non-interactively, and a stale
|
|
201
|
+
* CLI caps the runner it resolves at its own major.minor. The nudge goes to
|
|
202
|
+
* stderr, so stdout stays parseable.
|
|
203
|
+
*/
|
|
204
|
+
export function shouldShowNudge(env = process.env) {
|
|
200
205
|
if (env.TOT_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER) return false;
|
|
201
206
|
if (env.CI) return false;
|
|
202
|
-
if (!stream || !stream.isTTY) return false;
|
|
203
207
|
return true;
|
|
204
208
|
}
|
|
205
209
|
|
|
@@ -292,7 +296,7 @@ function refreshInBackground(env) {
|
|
|
292
296
|
*/
|
|
293
297
|
export function maybeNotifyUpdate(current, env = process.env, { stream = process.stderr } = {}) {
|
|
294
298
|
try {
|
|
295
|
-
if (shouldShowNudge(env
|
|
299
|
+
if (shouldShowNudge(env)) {
|
|
296
300
|
const notice = updateNotice(current, env);
|
|
297
301
|
if (notice) stream.write(`${renderNotice(notice, current)}\n`);
|
|
298
302
|
}
|