halfcycle 0.3.13 → 0.3.14
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/.claude-plugin/plugin.json +1 -1
- package/dist/banner-facts.d.ts +11 -7
- package/dist/banner-facts.d.ts.map +1 -1
- package/dist/banner.d.ts +58 -7
- package/dist/banner.d.ts.map +1 -1
- package/dist/bin.js +313 -259
- package/dist/bin.js.map +3 -3
- package/dist/confirm-identity.d.ts +30 -4
- package/dist/confirm-identity.d.ts.map +1 -1
- package/dist/control-origin.d.ts +6 -1
- package/dist/control-origin.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/own-engagement.d.ts +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1625,7 +1625,7 @@ function resolveControlOrigin(env = process.env) {
|
|
|
1625
1625
|
return { origin: DEFAULT_CONTROL_ORIGIN, source: "default" };
|
|
1626
1626
|
}
|
|
1627
1627
|
function controlOriginNote(resolved) {
|
|
1628
|
-
return resolved.source === "environment" ? `${resolved.origin} (from HALFCYCLE_SERVICE_URL)` : `${resolved.origin} (the
|
|
1628
|
+
return resolved.source === "environment" ? `${resolved.origin} (from HALFCYCLE_SERVICE_URL)` : `${resolved.origin} (the published one)`;
|
|
1629
1629
|
}
|
|
1630
1630
|
|
|
1631
1631
|
// dist/device-signin.js
|
|
@@ -1772,7 +1772,7 @@ var SignInRefused = class extends Error {
|
|
|
1772
1772
|
}
|
|
1773
1773
|
};
|
|
1774
1774
|
var SIGN_IN_TIMED_OUT = "timed-out";
|
|
1775
|
-
var SIGN_IN_TIMEOUT_MESSAGE = "Sign-in timed out: the Halfcycle
|
|
1775
|
+
var SIGN_IN_TIMEOUT_MESSAGE = "Sign-in timed out: the Halfcycle service stopped answering while this terminal was waiting for the browser. Nothing was created. Check your connection and run the command again.";
|
|
1776
1776
|
var SIGN_IN_NON_INTERACTIVE_MESSAGE = "Halfcycle needs a signed-in account and this looks like a non-interactive run (CI is set), so there is no browser to sign in with. Set HALFCYCLE_TOKEN in the environment to a Halfcycle credential and run this again. Nothing was created.";
|
|
1777
1777
|
var DEADLINE_SLACK_INTERVALS = 1;
|
|
1778
1778
|
var STILL_WAITING_MS = 15e3;
|
|
@@ -1859,7 +1859,7 @@ async function startDeviceAuth(serviceUrl) {
|
|
|
1859
1859
|
body: "{}"
|
|
1860
1860
|
});
|
|
1861
1861
|
} catch (err) {
|
|
1862
|
-
throw new SignInRefused(SIGN_IN_TIMED_OUT, `Could not reach the Halfcycle
|
|
1862
|
+
throw new SignInRefused(SIGN_IN_TIMED_OUT, `Could not reach the Halfcycle service at ${url} to start a sign-in: ${err instanceof Error ? err.message : String(err)}. Nothing was created.`);
|
|
1863
1863
|
}
|
|
1864
1864
|
const body = await res.json().catch(() => null);
|
|
1865
1865
|
if (res.status !== 201) {
|
|
@@ -1868,7 +1868,7 @@ async function startDeviceAuth(serviceUrl) {
|
|
|
1868
1868
|
}
|
|
1869
1869
|
const parsed = deviceAuthStartResponseSchema.safeParse(body);
|
|
1870
1870
|
if (!parsed.success) {
|
|
1871
|
-
throw new SignInRefused(SIGN_IN_TIMED_OUT, `The Halfcycle
|
|
1871
|
+
throw new SignInRefused(SIGN_IN_TIMED_OUT, `The Halfcycle service at ${url} answered a sign-in start this client cannot read. Either that service is older than this installer, or the address is not a Halfcycle service. Nothing was created.`);
|
|
1872
1872
|
}
|
|
1873
1873
|
return parsed.data;
|
|
1874
1874
|
}
|
|
@@ -1943,7 +1943,7 @@ async function collectDecidedCredential(serviceUrl, started, deps) {
|
|
|
1943
1943
|
});
|
|
1944
1944
|
body = await res.json().catch(() => null);
|
|
1945
1945
|
} catch (err) {
|
|
1946
|
-
lastProblem = `The browser finished signing you in, but this terminal could not reach the Halfcycle
|
|
1946
|
+
lastProblem = `The browser finished signing you in, but this terminal could not reach the Halfcycle service to collect the credential: ${err instanceof Error ? err.message : String(err)}. Run the command again.`;
|
|
1947
1947
|
continue;
|
|
1948
1948
|
}
|
|
1949
1949
|
const parsed = devicePollResponseSchema.safeParse(body);
|
|
@@ -2132,7 +2132,7 @@ async function requestEngagementValues(url, requestBody, credential, shape) {
|
|
|
2132
2132
|
body: JSON.stringify(requestBody)
|
|
2133
2133
|
});
|
|
2134
2134
|
} catch (err) {
|
|
2135
|
-
throw new Error(`[bundle install] Could not reach the Halfcycle
|
|
2135
|
+
throw new Error(`[bundle install] Could not reach the Halfcycle service at ${url}: ${err instanceof Error ? err.message : String(err)}. ${shape.nothingHappened}. ` + CONTROL_ORIGIN_HINT);
|
|
2136
2136
|
}
|
|
2137
2137
|
if (!res.ok) {
|
|
2138
2138
|
const detail = await res.text().catch(() => "");
|
|
@@ -2140,7 +2140,7 @@ async function requestEngagementValues(url, requestBody, credential, shape) {
|
|
|
2140
2140
|
if (refusal) {
|
|
2141
2141
|
throw new CreateEngagementRefused(res.status, refusal.message, refusal.error, `[bundle install] ${shape.action} failed: ${url} returned ${res.status}. ${refusal.message} ${shape.nothingHappened}.`);
|
|
2142
2142
|
}
|
|
2143
|
-
const wrongOrigin = res.status === 404 ? `That address answered, but it does not serve ${shape.route} \u2014 so it is not the
|
|
2143
|
+
const wrongOrigin = res.status === 404 ? `That address answered, but it does not serve ${shape.route} \u2014 so it is not the Halfcycle service. ` : "";
|
|
2144
2144
|
throw new Error(`[bundle install] ${shape.action} failed: ${url} returned ${res.status}. ${wrongOrigin}${detail ? `Response: ${detail.slice(0, 300)}. ` : ""}${shape.nothingHappened}. ` + CONTROL_ORIGIN_HINT);
|
|
2145
2145
|
}
|
|
2146
2146
|
const body = await res.json().catch(() => null);
|
|
@@ -2152,14 +2152,14 @@ async function requestEngagementValues(url, requestBody, credential, shape) {
|
|
|
2152
2152
|
["sessionToken", body.sessionToken]
|
|
2153
2153
|
]) {
|
|
2154
2154
|
if (value.trim() === "") {
|
|
2155
|
-
throw new Error(`[bundle install] The Halfcycle
|
|
2155
|
+
throw new Error(`[bundle install] The Halfcycle service at ${url} answered with a blank ${field} (the field is present but empty). An install cannot proceed on it: it would be written into this engagement's credential store, read back as a configured value, and every guard evaluation would fail against it for the life of the engagement. ${shape.nothingHappened} and nothing was written. ` + CONTROL_ORIGIN_HINT);
|
|
2156
2156
|
}
|
|
2157
2157
|
}
|
|
2158
2158
|
if (typeof body.mcpUrl !== "string" || body.mcpUrl.trim() === "") {
|
|
2159
|
-
throw new Error(`[bundle install] The Halfcycle
|
|
2159
|
+
throw new Error(`[bundle install] The Halfcycle service at ${url} created an engagement but did not say where its MCP server lives (no mcpUrl on the response). Without that address the install would write an MCP registration pointing nowhere, so nothing was written. Either that service is older than this installer, or ${url} is not a Halfcycle service.`);
|
|
2160
2160
|
}
|
|
2161
2161
|
if (typeof body.guardUrl !== "string" || body.guardUrl.trim() === "") {
|
|
2162
|
-
throw new Error(`[bundle install] The Halfcycle
|
|
2162
|
+
throw new Error(`[bundle install] The Halfcycle service at ${url} created an engagement but did not say where its guard service lives (no guardUrl on the response). Without that address the install would wire a guard hook that evaluates nothing, so nothing was written. Either that service is older than this installer, or ${url} is not a Halfcycle service.`);
|
|
2163
2163
|
}
|
|
2164
2164
|
const controlTelemetryUrl = typeof body.controlTelemetryUrl === "string" && body.controlTelemetryUrl.trim() !== "" ? body.controlTelemetryUrl.trim().replace(/\/+$/, "") : void 0;
|
|
2165
2165
|
return {
|
|
@@ -2218,12 +2218,284 @@ function refusedCredentialRemedy(source) {
|
|
|
2218
2218
|
case "stored":
|
|
2219
2219
|
return "That was this machine's saved sign-in and it has been discarded. Run the command again to sign in through your browser.";
|
|
2220
2220
|
case "browser-handoff":
|
|
2221
|
-
return "That credential was issued by this sign-in moments ago, so signing in again would produce the same result. This is a problem on the Halfcycle
|
|
2221
|
+
return "That credential was issued by this sign-in moments ago, so signing in again would produce the same result. This is a problem on the Halfcycle service rather than with your account.";
|
|
2222
2222
|
}
|
|
2223
2223
|
}
|
|
2224
2224
|
|
|
2225
2225
|
// dist/confirm-identity.js
|
|
2226
2226
|
import { createInterface } from "node:readline/promises";
|
|
2227
|
+
|
|
2228
|
+
// dist/banner.js
|
|
2229
|
+
var MARK_FULL = {
|
|
2230
|
+
width: 32,
|
|
2231
|
+
discRows: 7,
|
|
2232
|
+
lines: [
|
|
2233
|
+
" :+oshhhhso+:",
|
|
2234
|
+
" :sdMMMMMMMMMMMMds:",
|
|
2235
|
+
" :hMMMMMMMMMMMMMMMMMMh:",
|
|
2236
|
+
" oMMMMMMMMMMMMMMMMMMMMMMo",
|
|
2237
|
+
" oMMMMMMMMMMMMMMMMMMMMMMMMo",
|
|
2238
|
+
" NMMMMMMMMMMMMMMMMMMMMMMMMN",
|
|
2239
|
+
" :ssssssssssssssssssssssssss:",
|
|
2240
|
+
" +dddddddddddddddddddddddddd+",
|
|
2241
|
+
" Nd dN",
|
|
2242
|
+
" oMy yMo",
|
|
2243
|
+
" oMh: :hMo",
|
|
2244
|
+
" :hMy- -yMh:",
|
|
2245
|
+
" :sdNys++--++syNds:",
|
|
2246
|
+
" :+oshhhhso+:"
|
|
2247
|
+
]
|
|
2248
|
+
};
|
|
2249
|
+
var MARK_NARROW = {
|
|
2250
|
+
width: 24,
|
|
2251
|
+
discRows: 5,
|
|
2252
|
+
lines: [
|
|
2253
|
+
" -ohdMMMMdho-",
|
|
2254
|
+
" +dMMMMMMMMMMMMd+",
|
|
2255
|
+
" yMMMMMMMMMMMMMMMMy",
|
|
2256
|
+
" sMMMMMMMMMMMMMMMMMMs",
|
|
2257
|
+
" yhhhhhhhhhhhhhhhhhhy",
|
|
2258
|
+
" NdhhhhhhhhhhhhhhhhdN",
|
|
2259
|
+
" sd ds",
|
|
2260
|
+
" yd: :dy",
|
|
2261
|
+
" +dy+ +yd+",
|
|
2262
|
+
" -ohhhhhhhho-"
|
|
2263
|
+
]
|
|
2264
|
+
};
|
|
2265
|
+
var UNICODE_GLYPHS = {
|
|
2266
|
+
rule: "\u2500",
|
|
2267
|
+
swatch: "\u2584",
|
|
2268
|
+
dot: "\xB7",
|
|
2269
|
+
dash: "\u2014"
|
|
2270
|
+
};
|
|
2271
|
+
var ASCII_GLYPHS = {
|
|
2272
|
+
rule: "-",
|
|
2273
|
+
swatch: "#",
|
|
2274
|
+
dot: "|",
|
|
2275
|
+
dash: "-"
|
|
2276
|
+
};
|
|
2277
|
+
function toAscii(text) {
|
|
2278
|
+
let out = text;
|
|
2279
|
+
for (const key of Object.keys(UNICODE_GLYPHS)) {
|
|
2280
|
+
out = out.split(UNICODE_GLYPHS[key]).join(ASCII_GLYPHS[key]);
|
|
2281
|
+
}
|
|
2282
|
+
return out.replace(/[^ -~]/g, "?");
|
|
2283
|
+
}
|
|
2284
|
+
var INK = {
|
|
2285
|
+
/** `--text` — the terminal's own foreground, never one we picked. */
|
|
2286
|
+
plain: "",
|
|
2287
|
+
/** `--muted` — dimmed default ink, so it is grey against whatever the background is. */
|
|
2288
|
+
dim: "2",
|
|
2289
|
+
/** `--faint` / `--faded` — bright black, the one ANSI grey that is a colour. */
|
|
2290
|
+
faint: "90",
|
|
2291
|
+
/** Not a colour: emphasis, used with whatever ink is already in force. */
|
|
2292
|
+
bold: "1",
|
|
2293
|
+
/** `--signal` — yellow, the nearest ANSI seat for the brand's gold. */
|
|
2294
|
+
key: "33",
|
|
2295
|
+
/** `--signal`, brighter: the one value on a screen that must be found first. */
|
|
2296
|
+
keyBold: "33;1",
|
|
2297
|
+
/** `--good` — the console's affirmative. */
|
|
2298
|
+
good: "32",
|
|
2299
|
+
/** `--bad` — the console's negative. */
|
|
2300
|
+
bad: "31"
|
|
2301
|
+
};
|
|
2302
|
+
var SWATCH_SGR = [
|
|
2303
|
+
INK.dim,
|
|
2304
|
+
INK.faint,
|
|
2305
|
+
INK.plain,
|
|
2306
|
+
INK.key,
|
|
2307
|
+
INK.keyBold,
|
|
2308
|
+
INK.good,
|
|
2309
|
+
INK.bad
|
|
2310
|
+
];
|
|
2311
|
+
var ESC = "\x1B";
|
|
2312
|
+
var RESET = `${ESC}[0m`;
|
|
2313
|
+
function paint(segments, colour) {
|
|
2314
|
+
return segments.map((s) => colour && s.sgr !== "" ? `${ESC}[${s.sgr}m${s.text}${RESET}` : s.text).join("");
|
|
2315
|
+
}
|
|
2316
|
+
function ink(name, text, colour) {
|
|
2317
|
+
const sgr = INK[name];
|
|
2318
|
+
return colour && sgr !== "" ? `${ESC}[${sgr}m${text}${RESET}` : text;
|
|
2319
|
+
}
|
|
2320
|
+
var GAP = 4;
|
|
2321
|
+
var FULL_LAYOUT = { art: MARK_FULL, label: 13, rule: 28, palette: true, minColumns: 76 };
|
|
2322
|
+
var NARROW_LAYOUT = { art: MARK_NARROW, label: 10, rule: 20, palette: false, minColumns: 48 };
|
|
2323
|
+
var DEFAULT_COLUMNS = 80;
|
|
2324
|
+
function usableColumns(environment) {
|
|
2325
|
+
const columns = environment.columns;
|
|
2326
|
+
return columns !== void 0 && columns > 0 ? columns : DEFAULT_COLUMNS;
|
|
2327
|
+
}
|
|
2328
|
+
function isSet(value) {
|
|
2329
|
+
return value !== void 0 && value !== "";
|
|
2330
|
+
}
|
|
2331
|
+
function plainTextRequested(env) {
|
|
2332
|
+
return isSet(env["NO_COLOR"]) || env["TERM"] === "dumb";
|
|
2333
|
+
}
|
|
2334
|
+
function decideCut(environment = {}) {
|
|
2335
|
+
const env = environment.env ?? {};
|
|
2336
|
+
if (environment.quiet === true)
|
|
2337
|
+
return "none";
|
|
2338
|
+
if (environment.isTTY !== true)
|
|
2339
|
+
return "line";
|
|
2340
|
+
if (plainTextRequested(env))
|
|
2341
|
+
return "line";
|
|
2342
|
+
const columns = usableColumns(environment);
|
|
2343
|
+
if (columns >= FULL_LAYOUT.minColumns)
|
|
2344
|
+
return "full";
|
|
2345
|
+
if (columns >= NARROW_LAYOUT.minColumns)
|
|
2346
|
+
return "narrow";
|
|
2347
|
+
return "line";
|
|
2348
|
+
}
|
|
2349
|
+
function decideColour(environment = {}) {
|
|
2350
|
+
const env = environment.env ?? {};
|
|
2351
|
+
const force = env["FORCE_COLOR"];
|
|
2352
|
+
if (isSet(force))
|
|
2353
|
+
return force !== "0";
|
|
2354
|
+
if (plainTextRequested(env))
|
|
2355
|
+
return false;
|
|
2356
|
+
return environment.isTTY === true;
|
|
2357
|
+
}
|
|
2358
|
+
function decideUnicode(environment = {}) {
|
|
2359
|
+
const env = environment.env ?? {};
|
|
2360
|
+
if ((environment.platform ?? "") !== "win32") {
|
|
2361
|
+
const locale = env["LC_ALL"] ?? env["LC_CTYPE"] ?? env["LANG"] ?? "";
|
|
2362
|
+
return locale === "" || /utf-?8/i.test(locale);
|
|
2363
|
+
}
|
|
2364
|
+
return isSet(env["WT_SESSION"]) || isSet(env["TERMINUS_SUBLIME"]) || env["ConEmuTask"] === "{cmd::Cmder}" || env["TERM_PROGRAM"] === "vscode";
|
|
2365
|
+
}
|
|
2366
|
+
function padEnd(text, width) {
|
|
2367
|
+
return text + " ".repeat(Math.max(0, width - text.length));
|
|
2368
|
+
}
|
|
2369
|
+
function clip(text, width) {
|
|
2370
|
+
if (width < 8 || text.length <= width)
|
|
2371
|
+
return text;
|
|
2372
|
+
return `${text.slice(0, width - 3)}...`;
|
|
2373
|
+
}
|
|
2374
|
+
function paletteRow(swatch) {
|
|
2375
|
+
const row = [];
|
|
2376
|
+
SWATCH_SGR.forEach((sgr, i) => {
|
|
2377
|
+
if (i > 0)
|
|
2378
|
+
row.push({ text: " ", sgr: INK.plain });
|
|
2379
|
+
row.push({ text: swatch.repeat(2), sgr });
|
|
2380
|
+
});
|
|
2381
|
+
return row;
|
|
2382
|
+
}
|
|
2383
|
+
function factColumn(content, layout, glyphs, text, valueWidth) {
|
|
2384
|
+
const rows = [];
|
|
2385
|
+
const head = text(content.head);
|
|
2386
|
+
const at = head.indexOf("@");
|
|
2387
|
+
rows.push(at < 0 ? [{ text: head, sgr: INK.keyBold }] : [
|
|
2388
|
+
{ text: head.slice(0, at), sgr: INK.keyBold },
|
|
2389
|
+
{ text: "@", sgr: INK.dim },
|
|
2390
|
+
{ text: head.slice(at + 1), sgr: INK.bold }
|
|
2391
|
+
]);
|
|
2392
|
+
rows.push([{ text: glyphs.rule.repeat(layout.rule), sgr: INK.dim }]);
|
|
2393
|
+
const narrow = layout.art === MARK_NARROW;
|
|
2394
|
+
for (const fact2 of content.facts) {
|
|
2395
|
+
const raw = narrow ? fact2.narrow : fact2.value;
|
|
2396
|
+
if (raw === void 0)
|
|
2397
|
+
continue;
|
|
2398
|
+
rows.push([
|
|
2399
|
+
{ text: padEnd(`${text(fact2.label)}:`, layout.label), sgr: INK.key },
|
|
2400
|
+
{ text: clip(text(raw), valueWidth), sgr: INK.plain }
|
|
2401
|
+
]);
|
|
2402
|
+
}
|
|
2403
|
+
if (layout.palette) {
|
|
2404
|
+
rows.push([]);
|
|
2405
|
+
rows.push(paletteRow(glyphs.swatch));
|
|
2406
|
+
}
|
|
2407
|
+
return rows;
|
|
2408
|
+
}
|
|
2409
|
+
var MARGIN = 2;
|
|
2410
|
+
function lastSentenceStart(line) {
|
|
2411
|
+
const at = line.lastIndexOf(". ");
|
|
2412
|
+
return at < 0 ? 0 : at + 2;
|
|
2413
|
+
}
|
|
2414
|
+
function taglineRow(line, first, last) {
|
|
2415
|
+
const indent = { text: " ", sgr: INK.plain };
|
|
2416
|
+
if (first)
|
|
2417
|
+
return [indent, { text: line, sgr: INK.keyBold }];
|
|
2418
|
+
if (!last)
|
|
2419
|
+
return [indent, { text: line, sgr: INK.dim }];
|
|
2420
|
+
const at = lastSentenceStart(line);
|
|
2421
|
+
if (at === 0)
|
|
2422
|
+
return [indent, { text: line, sgr: INK.key }];
|
|
2423
|
+
return [
|
|
2424
|
+
indent,
|
|
2425
|
+
{ text: line.slice(0, at), sgr: INK.dim },
|
|
2426
|
+
{ text: line.slice(at), sgr: INK.key }
|
|
2427
|
+
];
|
|
2428
|
+
}
|
|
2429
|
+
function renderBlock(content, layout, environment) {
|
|
2430
|
+
const unicode = decideUnicode(environment);
|
|
2431
|
+
const colour = decideColour(environment);
|
|
2432
|
+
const glyphs = unicode ? UNICODE_GLYPHS : ASCII_GLYPHS;
|
|
2433
|
+
const text = (raw) => unicode ? raw : toAscii(raw);
|
|
2434
|
+
const art = layout.art;
|
|
2435
|
+
const valueWidth = usableColumns(environment) - (art.width + GAP + layout.label);
|
|
2436
|
+
const right = factColumn(content, layout, glyphs, text, valueWidth);
|
|
2437
|
+
const top = Math.max(0, Math.floor((art.lines.length - right.length) / 2));
|
|
2438
|
+
const height = Math.max(art.lines.length, right.length + top);
|
|
2439
|
+
const lines = Array.from({ length: MARGIN }, () => []);
|
|
2440
|
+
for (let i = 0; i < height; i++) {
|
|
2441
|
+
const artLine = art.lines[i] ?? "";
|
|
2442
|
+
const segments = [];
|
|
2443
|
+
if (artLine.length > 0) {
|
|
2444
|
+
segments.push({ text: artLine, sgr: i < art.discRows ? INK.plain : INK.dim });
|
|
2445
|
+
}
|
|
2446
|
+
const rightRow = right[i - top];
|
|
2447
|
+
if (rightRow !== void 0 && rightRow.length > 0) {
|
|
2448
|
+
segments.push({ text: " ".repeat(Math.max(0, art.width + GAP - artLine.length)), sgr: INK.plain });
|
|
2449
|
+
segments.push(...rightRow);
|
|
2450
|
+
}
|
|
2451
|
+
lines.push(segments);
|
|
2452
|
+
}
|
|
2453
|
+
const tagline = layout.art === MARK_NARROW ? content.tagNarrow ?? content.tag : content.tag;
|
|
2454
|
+
lines.push([]);
|
|
2455
|
+
tagline.forEach((line, i) => {
|
|
2456
|
+
lines.push(taglineRow(text(line), i === 0, i === tagline.length - 1));
|
|
2457
|
+
});
|
|
2458
|
+
for (let i = 0; i < MARGIN; i++)
|
|
2459
|
+
lines.push([]);
|
|
2460
|
+
return lines.map((segments) => paint(segments, colour)).join("\n");
|
|
2461
|
+
}
|
|
2462
|
+
function renderLine(content, environment) {
|
|
2463
|
+
const unicode = decideUnicode(environment);
|
|
2464
|
+
const dot = unicode ? UNICODE_GLYPHS.dot : ASCII_GLYPHS.dot;
|
|
2465
|
+
const named = content.version === "" ? "Halfcycle" : `Halfcycle v${content.version}`;
|
|
2466
|
+
const raw = `${named} ${dot} ${content.url}`;
|
|
2467
|
+
return unicode ? raw : toAscii(raw);
|
|
2468
|
+
}
|
|
2469
|
+
function renderBanner(content, environment = {}) {
|
|
2470
|
+
switch (decideCut(environment)) {
|
|
2471
|
+
case "none":
|
|
2472
|
+
return "";
|
|
2473
|
+
case "line":
|
|
2474
|
+
return renderLine(content, environment);
|
|
2475
|
+
case "narrow":
|
|
2476
|
+
return renderBlock(content, NARROW_LAYOUT, environment);
|
|
2477
|
+
case "full":
|
|
2478
|
+
return renderBlock(content, FULL_LAYOUT, environment);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
function printBanner(sink, content, environment = {}) {
|
|
2482
|
+
const text = renderBanner(content, environment);
|
|
2483
|
+
if (text === "")
|
|
2484
|
+
return;
|
|
2485
|
+
sink.write(`${text}
|
|
2486
|
+
`);
|
|
2487
|
+
}
|
|
2488
|
+
function currentEnvironment(quiet2) {
|
|
2489
|
+
return {
|
|
2490
|
+
columns: process.stdout.columns,
|
|
2491
|
+
isTTY: process.stdout.isTTY === true,
|
|
2492
|
+
quiet: quiet2,
|
|
2493
|
+
env: process.env,
|
|
2494
|
+
platform: process.platform
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// dist/confirm-identity.js
|
|
2227
2499
|
var IDENTITY_TIMEOUT_MS = 5e3;
|
|
2228
2500
|
var IDENTITY_DECLINED = "identity-declined";
|
|
2229
2501
|
async function describeAccount(serviceUrl, credential, fetchImpl = fetch) {
|
|
@@ -2245,14 +2517,14 @@ async function describeAccount(serviceUrl, credential, fetchImpl = fetch) {
|
|
|
2245
2517
|
clearTimeout(timer);
|
|
2246
2518
|
}
|
|
2247
2519
|
}
|
|
2248
|
-
function accountLabel(identity, storedAccountId) {
|
|
2520
|
+
function accountLabel(identity, storedAccountId, verbose2 = false) {
|
|
2249
2521
|
const accountId = identity?.accountId ?? storedAccountId;
|
|
2250
2522
|
if (identity?.email !== void 0 && identity.email.trim() !== "") {
|
|
2251
|
-
return accountId !== void 0 ? `${identity.email} (account ${accountId})` : identity.email;
|
|
2523
|
+
return verbose2 && accountId !== void 0 ? `${identity.email} (account ${accountId})` : identity.email;
|
|
2252
2524
|
}
|
|
2253
2525
|
if (accountId !== void 0)
|
|
2254
2526
|
return `account ${accountId} (no email on record for it)`;
|
|
2255
|
-
return "the account this credential belongs to, which this
|
|
2527
|
+
return "the account this credential belongs to, which this service did not name";
|
|
2256
2528
|
}
|
|
2257
2529
|
function onlyDate(iso) {
|
|
2258
2530
|
if (iso === void 0)
|
|
@@ -2263,10 +2535,10 @@ function onlyDate(iso) {
|
|
|
2263
2535
|
function actClause(act) {
|
|
2264
2536
|
return act.kind === "create" ? `create a NEW project for that account, and install into ${act.targetRepo}` : `join the project this repository is pinned to (${act.engagementId}) as that account, and install into ${act.targetRepo}`;
|
|
2265
2537
|
}
|
|
2266
|
-
async function defaultAsk(
|
|
2538
|
+
async function defaultAsk(question2) {
|
|
2267
2539
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2268
2540
|
try {
|
|
2269
|
-
return await rl.question(
|
|
2541
|
+
return await rl.question(question2);
|
|
2270
2542
|
} finally {
|
|
2271
2543
|
rl.close();
|
|
2272
2544
|
process.stdin.pause();
|
|
@@ -2284,7 +2556,10 @@ function actingAs(credential, identity) {
|
|
|
2284
2556
|
const accountId = identity?.accountId ?? credential.accountId;
|
|
2285
2557
|
return accountId === void 0 ? credential : { ...credential, accountId };
|
|
2286
2558
|
}
|
|
2287
|
-
function
|
|
2559
|
+
function question(colour) {
|
|
2560
|
+
return `[halfcycle] Continue as that account? ${ink("good", "[y]", colour)} yes ${ink("key", "[s]", colour)} sign in as someone else ${ink("faint", "[anything else]", colour)} stop: `;
|
|
2561
|
+
}
|
|
2562
|
+
function armScript(credential, act, label, plainLabel, home) {
|
|
2288
2563
|
switch (credential.source) {
|
|
2289
2564
|
case "browser-handoff":
|
|
2290
2565
|
return {
|
|
@@ -2310,7 +2585,7 @@ function armScript(credential, act, label, home) {
|
|
|
2310
2585
|
noTerminalNote: "",
|
|
2311
2586
|
switchOpening: `[halfcycle] Signing you in through your browser \u2014 this install will use that account instead.
|
|
2312
2587
|
`,
|
|
2313
|
-
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. HALFCYCLE_TOKEN in this environment is the credential for ${
|
|
2588
|
+
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. HALFCYCLE_TOKEN in this environment is the credential for ${plainLabel}, and it takes precedence over any saved sign-in \u2014 so unset it, or set it to your own account's credential, before running this again.`,
|
|
2314
2589
|
// The switch is real for THIS run (the new credential is what gets used) and it
|
|
2315
2590
|
// does not persist: `obtainCredential` reads the variable first, so the next run
|
|
2316
2591
|
// is the same variable again. Said here rather than discovered tomorrow.
|
|
@@ -2336,7 +2611,7 @@ function armScript(credential, act, label, home) {
|
|
|
2336
2611
|
`,
|
|
2337
2612
|
switchOpening: `[halfcycle] Forgetting this machine's saved sign-in and signing you in through your browser.
|
|
2338
2613
|
`,
|
|
2339
|
-
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. This machine's saved sign-in is for ${
|
|
2614
|
+
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. This machine's saved sign-in is for ${plainLabel}. Run this again and answer "s" to sign in as a different account, or remove ${accountStorePath(home)} to be asked for a sign-in next time.`,
|
|
2340
2615
|
afterSwitch: ""
|
|
2341
2616
|
};
|
|
2342
2617
|
}
|
|
@@ -2344,10 +2619,12 @@ function armScript(credential, act, label, home) {
|
|
|
2344
2619
|
}
|
|
2345
2620
|
async function confirmActingIdentity(serviceUrl, credential, act, deps = {}) {
|
|
2346
2621
|
const write = deps.write ?? ((text) => process.stdout.write(text));
|
|
2622
|
+
const colour = deps.colour ?? decideColour({ isTTY: process.stdout.isTTY === true, env: deps.env ?? process.env });
|
|
2347
2623
|
const identity = await describeAccount(serviceUrl, credential.credential, deps.fetchImpl);
|
|
2348
|
-
const
|
|
2624
|
+
const plainLabel = accountLabel(identity, credential.accountId, deps.verbose === true);
|
|
2625
|
+
const label = ink("keyBold", plainLabel, colour);
|
|
2349
2626
|
const acting = actingAs(credential, identity);
|
|
2350
|
-
const script = armScript(credential, act, label, deps.home);
|
|
2627
|
+
const script = armScript(credential, act, label, plainLabel, deps.home);
|
|
2351
2628
|
write(script.preamble);
|
|
2352
2629
|
if (!script.asks)
|
|
2353
2630
|
return acting;
|
|
@@ -2363,14 +2640,15 @@ async function confirmActingIdentity(serviceUrl, credential, act, deps = {}) {
|
|
|
2363
2640
|
return acting;
|
|
2364
2641
|
}
|
|
2365
2642
|
const ask = deps.ask ?? defaultAsk;
|
|
2366
|
-
|
|
2643
|
+
write("\n");
|
|
2644
|
+
const decision = readDecision(await ask(question(colour)));
|
|
2367
2645
|
if (decision === "proceed")
|
|
2368
2646
|
return acting;
|
|
2369
2647
|
if (decision === "switch-account") {
|
|
2370
2648
|
write(script.switchOpening);
|
|
2371
2649
|
const replacement = await switchAccount(serviceUrl, deps);
|
|
2372
2650
|
const replacementIdentity = await describeAccount(serviceUrl, replacement.credential, deps.fetchImpl);
|
|
2373
|
-
write(`[halfcycle] Signed in as ${accountLabel(replacementIdentity, replacement.accountId)}. This install will ${actClause(act)}.
|
|
2651
|
+
write(`[halfcycle] Signed in as ${ink("keyBold", accountLabel(replacementIdentity, replacement.accountId, deps.verbose === true), colour)}. This install will ${actClause(act)}.
|
|
2374
2652
|
`);
|
|
2375
2653
|
if (script.afterSwitch !== "")
|
|
2376
2654
|
write(script.afterSwitch);
|
|
@@ -2882,7 +3160,7 @@ async function openPhase(credential, phase, entry) {
|
|
|
2882
3160
|
body: JSON.stringify({ phase, entry })
|
|
2883
3161
|
});
|
|
2884
3162
|
} catch (err) {
|
|
2885
|
-
throw new Error(`[halfcycle] Could not reach the Halfcycle
|
|
3163
|
+
throw new Error(`[halfcycle] Could not reach the Halfcycle service at ${url}: ${err instanceof Error ? err.message : String(err)}. No phase was opened.`);
|
|
2886
3164
|
}
|
|
2887
3165
|
if (!res.ok) {
|
|
2888
3166
|
const body2 = await res.json().catch(() => null);
|
|
@@ -2935,7 +3213,7 @@ async function closePhase(credential, phase, outcome, close) {
|
|
|
2935
3213
|
body: JSON.stringify({ phase, acceptanceOutcome: outcome, close })
|
|
2936
3214
|
});
|
|
2937
3215
|
} catch (err) {
|
|
2938
|
-
throw new Error(`[halfcycle] Could not reach the Halfcycle
|
|
3216
|
+
throw new Error(`[halfcycle] Could not reach the Halfcycle service at ${url}: ${err instanceof Error ? err.message : String(err)}. The phase was not closed.`);
|
|
2939
3217
|
}
|
|
2940
3218
|
if (!res.ok) {
|
|
2941
3219
|
const body2 = await res.json().catch(() => null);
|
|
@@ -3066,234 +3344,6 @@ var PLACEHOLDERS = {
|
|
|
3066
3344
|
"--evidence": '"\u2026"'
|
|
3067
3345
|
};
|
|
3068
3346
|
|
|
3069
|
-
// dist/banner.js
|
|
3070
|
-
var MARK_FULL = {
|
|
3071
|
-
width: 32,
|
|
3072
|
-
discRows: 7,
|
|
3073
|
-
lines: [
|
|
3074
|
-
" :+oshhhhso+:",
|
|
3075
|
-
" :sdMMMMMMMMMMMMds:",
|
|
3076
|
-
" :hMMMMMMMMMMMMMMMMMMh:",
|
|
3077
|
-
" oMMMMMMMMMMMMMMMMMMMMMMo",
|
|
3078
|
-
" oMMMMMMMMMMMMMMMMMMMMMMMMo",
|
|
3079
|
-
" NMMMMMMMMMMMMMMMMMMMMMMMMN",
|
|
3080
|
-
" :ssssssssssssssssssssssssss:",
|
|
3081
|
-
" +dddddddddddddddddddddddddd+",
|
|
3082
|
-
" Nd dN",
|
|
3083
|
-
" oMy yMo",
|
|
3084
|
-
" oMh: :hMo",
|
|
3085
|
-
" :hMy- -yMh:",
|
|
3086
|
-
" :sdNys++--++syNds:",
|
|
3087
|
-
" :+oshhhhso+:"
|
|
3088
|
-
]
|
|
3089
|
-
};
|
|
3090
|
-
var MARK_NARROW = {
|
|
3091
|
-
width: 24,
|
|
3092
|
-
discRows: 5,
|
|
3093
|
-
lines: [
|
|
3094
|
-
" -ohdMMMMdho-",
|
|
3095
|
-
" +dMMMMMMMMMMMMd+",
|
|
3096
|
-
" yMMMMMMMMMMMMMMMMy",
|
|
3097
|
-
" sMMMMMMMMMMMMMMMMMMs",
|
|
3098
|
-
" yhhhhhhhhhhhhhhhhhhy",
|
|
3099
|
-
" NdhhhhhhhhhhhhhhhhdN",
|
|
3100
|
-
" sd ds",
|
|
3101
|
-
" yd: :dy",
|
|
3102
|
-
" +dy+ +yd+",
|
|
3103
|
-
" -ohhhhhhhho-"
|
|
3104
|
-
]
|
|
3105
|
-
};
|
|
3106
|
-
var UNICODE_GLYPHS = {
|
|
3107
|
-
rule: "\u2500",
|
|
3108
|
-
swatch: "\u2584",
|
|
3109
|
-
dot: "\xB7",
|
|
3110
|
-
dash: "\u2014"
|
|
3111
|
-
};
|
|
3112
|
-
var ASCII_GLYPHS = {
|
|
3113
|
-
rule: "-",
|
|
3114
|
-
swatch: "#",
|
|
3115
|
-
dot: "|",
|
|
3116
|
-
dash: "-"
|
|
3117
|
-
};
|
|
3118
|
-
function toAscii(text) {
|
|
3119
|
-
let out = text;
|
|
3120
|
-
for (const key of Object.keys(UNICODE_GLYPHS)) {
|
|
3121
|
-
out = out.split(UNICODE_GLYPHS[key]).join(ASCII_GLYPHS[key]);
|
|
3122
|
-
}
|
|
3123
|
-
return out.replace(/[^ -~]/g, "?");
|
|
3124
|
-
}
|
|
3125
|
-
var INK = {
|
|
3126
|
-
plain: "",
|
|
3127
|
-
dim: "2",
|
|
3128
|
-
bold: "1",
|
|
3129
|
-
/** Yellow — the nearest ANSI seat for the brand's gold, used for labels and the URL. */
|
|
3130
|
-
key: "33",
|
|
3131
|
-
keyBold: "33;1"
|
|
3132
|
-
};
|
|
3133
|
-
var SWATCH_SGR = ["90", "31", "32", "33", "34", "35", "36", "37"];
|
|
3134
|
-
var ESC = "\x1B";
|
|
3135
|
-
var RESET = `${ESC}[0m`;
|
|
3136
|
-
function paint(segments, colour) {
|
|
3137
|
-
return segments.map((s) => colour && s.sgr !== "" ? `${ESC}[${s.sgr}m${s.text}${RESET}` : s.text).join("");
|
|
3138
|
-
}
|
|
3139
|
-
var GAP = 4;
|
|
3140
|
-
var FULL_LAYOUT = { art: MARK_FULL, label: 13, rule: 28, palette: true, minColumns: 76 };
|
|
3141
|
-
var NARROW_LAYOUT = { art: MARK_NARROW, label: 10, rule: 20, palette: false, minColumns: 48 };
|
|
3142
|
-
var DEFAULT_COLUMNS = 80;
|
|
3143
|
-
function usableColumns(environment) {
|
|
3144
|
-
const columns = environment.columns;
|
|
3145
|
-
return columns !== void 0 && columns > 0 ? columns : DEFAULT_COLUMNS;
|
|
3146
|
-
}
|
|
3147
|
-
function isSet(value) {
|
|
3148
|
-
return value !== void 0 && value !== "";
|
|
3149
|
-
}
|
|
3150
|
-
function plainTextRequested(env) {
|
|
3151
|
-
return isSet(env["NO_COLOR"]) || env["TERM"] === "dumb";
|
|
3152
|
-
}
|
|
3153
|
-
function decideCut(environment = {}) {
|
|
3154
|
-
const env = environment.env ?? {};
|
|
3155
|
-
if (environment.quiet === true)
|
|
3156
|
-
return "none";
|
|
3157
|
-
if (environment.isTTY !== true)
|
|
3158
|
-
return "line";
|
|
3159
|
-
if (plainTextRequested(env))
|
|
3160
|
-
return "line";
|
|
3161
|
-
const columns = usableColumns(environment);
|
|
3162
|
-
if (columns >= FULL_LAYOUT.minColumns)
|
|
3163
|
-
return "full";
|
|
3164
|
-
if (columns >= NARROW_LAYOUT.minColumns)
|
|
3165
|
-
return "narrow";
|
|
3166
|
-
return "line";
|
|
3167
|
-
}
|
|
3168
|
-
function decideColour(environment = {}) {
|
|
3169
|
-
const env = environment.env ?? {};
|
|
3170
|
-
const force = env["FORCE_COLOR"];
|
|
3171
|
-
if (isSet(force))
|
|
3172
|
-
return force !== "0";
|
|
3173
|
-
if (plainTextRequested(env))
|
|
3174
|
-
return false;
|
|
3175
|
-
return environment.isTTY === true;
|
|
3176
|
-
}
|
|
3177
|
-
function decideUnicode(environment = {}) {
|
|
3178
|
-
const env = environment.env ?? {};
|
|
3179
|
-
if ((environment.platform ?? "") !== "win32") {
|
|
3180
|
-
const locale = env["LC_ALL"] ?? env["LC_CTYPE"] ?? env["LANG"] ?? "";
|
|
3181
|
-
return locale === "" || /utf-?8/i.test(locale);
|
|
3182
|
-
}
|
|
3183
|
-
return isSet(env["WT_SESSION"]) || isSet(env["TERMINUS_SUBLIME"]) || env["ConEmuTask"] === "{cmd::Cmder}" || env["TERM_PROGRAM"] === "vscode";
|
|
3184
|
-
}
|
|
3185
|
-
function padEnd(text, width) {
|
|
3186
|
-
return text + " ".repeat(Math.max(0, width - text.length));
|
|
3187
|
-
}
|
|
3188
|
-
function clip(text, width) {
|
|
3189
|
-
if (width < 8 || text.length <= width)
|
|
3190
|
-
return text;
|
|
3191
|
-
return `${text.slice(0, width - 3)}...`;
|
|
3192
|
-
}
|
|
3193
|
-
function paletteRow(swatch) {
|
|
3194
|
-
const row = [];
|
|
3195
|
-
SWATCH_SGR.forEach((sgr, i) => {
|
|
3196
|
-
if (i > 0)
|
|
3197
|
-
row.push({ text: " ", sgr: INK.plain });
|
|
3198
|
-
row.push({ text: swatch.repeat(2), sgr });
|
|
3199
|
-
});
|
|
3200
|
-
return row;
|
|
3201
|
-
}
|
|
3202
|
-
function factColumn(content, layout, glyphs, text, valueWidth) {
|
|
3203
|
-
const rows = [];
|
|
3204
|
-
const head = text(content.head);
|
|
3205
|
-
const at = head.indexOf("@");
|
|
3206
|
-
rows.push(at < 0 ? [{ text: head, sgr: INK.keyBold }] : [
|
|
3207
|
-
{ text: head.slice(0, at), sgr: INK.keyBold },
|
|
3208
|
-
{ text: "@", sgr: INK.dim },
|
|
3209
|
-
{ text: head.slice(at + 1), sgr: INK.bold }
|
|
3210
|
-
]);
|
|
3211
|
-
rows.push([{ text: glyphs.rule.repeat(layout.rule), sgr: INK.dim }]);
|
|
3212
|
-
const narrow = layout.art === MARK_NARROW;
|
|
3213
|
-
for (const fact2 of content.facts) {
|
|
3214
|
-
const raw = narrow ? fact2.narrow : fact2.value;
|
|
3215
|
-
if (raw === void 0)
|
|
3216
|
-
continue;
|
|
3217
|
-
rows.push([
|
|
3218
|
-
{ text: padEnd(`${text(fact2.label)}:`, layout.label), sgr: INK.key },
|
|
3219
|
-
{ text: clip(text(raw), valueWidth), sgr: INK.plain }
|
|
3220
|
-
]);
|
|
3221
|
-
}
|
|
3222
|
-
if (layout.palette) {
|
|
3223
|
-
rows.push([]);
|
|
3224
|
-
rows.push(paletteRow(glyphs.swatch));
|
|
3225
|
-
}
|
|
3226
|
-
return rows;
|
|
3227
|
-
}
|
|
3228
|
-
function renderBlock(content, layout, environment) {
|
|
3229
|
-
const unicode = decideUnicode(environment);
|
|
3230
|
-
const colour = decideColour(environment);
|
|
3231
|
-
const glyphs = unicode ? UNICODE_GLYPHS : ASCII_GLYPHS;
|
|
3232
|
-
const text = (raw) => unicode ? raw : toAscii(raw);
|
|
3233
|
-
const art = layout.art;
|
|
3234
|
-
const valueWidth = usableColumns(environment) - (art.width + GAP + layout.label);
|
|
3235
|
-
const right = factColumn(content, layout, glyphs, text, valueWidth);
|
|
3236
|
-
const top = Math.max(0, Math.floor((art.lines.length - right.length) / 2));
|
|
3237
|
-
const height = Math.max(art.lines.length, right.length + top);
|
|
3238
|
-
const lines = [];
|
|
3239
|
-
for (let i = 0; i < height; i++) {
|
|
3240
|
-
const artLine = art.lines[i] ?? "";
|
|
3241
|
-
const segments = [];
|
|
3242
|
-
if (artLine.length > 0) {
|
|
3243
|
-
segments.push({ text: artLine, sgr: i < art.discRows ? INK.plain : INK.dim });
|
|
3244
|
-
}
|
|
3245
|
-
const rightRow = right[i - top];
|
|
3246
|
-
if (rightRow !== void 0 && rightRow.length > 0) {
|
|
3247
|
-
segments.push({ text: " ".repeat(Math.max(0, art.width + GAP - artLine.length)), sgr: INK.plain });
|
|
3248
|
-
segments.push(...rightRow);
|
|
3249
|
-
}
|
|
3250
|
-
lines.push(segments);
|
|
3251
|
-
}
|
|
3252
|
-
const tagline = layout.art === MARK_NARROW ? content.tagNarrow ?? content.tag : content.tag;
|
|
3253
|
-
lines.push([]);
|
|
3254
|
-
tagline.forEach((line, i) => {
|
|
3255
|
-
lines.push([{ text: ` ${text(line)}`, sgr: i === 0 ? INK.bold : INK.dim }]);
|
|
3256
|
-
});
|
|
3257
|
-
lines.push([]);
|
|
3258
|
-
lines.push([{ text: ` ${text(content.url)}`, sgr: INK.key }]);
|
|
3259
|
-
return lines.map((segments) => paint(segments, colour)).join("\n");
|
|
3260
|
-
}
|
|
3261
|
-
function renderLine(content, environment) {
|
|
3262
|
-
const unicode = decideUnicode(environment);
|
|
3263
|
-
const dot = unicode ? UNICODE_GLYPHS.dot : ASCII_GLYPHS.dot;
|
|
3264
|
-
const named = content.version === "" ? "Halfcycle" : `Halfcycle v${content.version}`;
|
|
3265
|
-
const raw = `${named} ${dot} ${content.url}`;
|
|
3266
|
-
return unicode ? raw : toAscii(raw);
|
|
3267
|
-
}
|
|
3268
|
-
function renderBanner(content, environment = {}) {
|
|
3269
|
-
switch (decideCut(environment)) {
|
|
3270
|
-
case "none":
|
|
3271
|
-
return "";
|
|
3272
|
-
case "line":
|
|
3273
|
-
return renderLine(content, environment);
|
|
3274
|
-
case "narrow":
|
|
3275
|
-
return renderBlock(content, NARROW_LAYOUT, environment);
|
|
3276
|
-
case "full":
|
|
3277
|
-
return renderBlock(content, FULL_LAYOUT, environment);
|
|
3278
|
-
}
|
|
3279
|
-
}
|
|
3280
|
-
function printBanner(sink, content, environment = {}) {
|
|
3281
|
-
const text = renderBanner(content, environment);
|
|
3282
|
-
if (text === "")
|
|
3283
|
-
return;
|
|
3284
|
-
sink.write(`${text}
|
|
3285
|
-
`);
|
|
3286
|
-
}
|
|
3287
|
-
function currentEnvironment(quiet2) {
|
|
3288
|
-
return {
|
|
3289
|
-
columns: process.stdout.columns,
|
|
3290
|
-
isTTY: process.stdout.isTTY === true,
|
|
3291
|
-
quiet: quiet2,
|
|
3292
|
-
env: process.env,
|
|
3293
|
-
platform: process.platform
|
|
3294
|
-
};
|
|
3295
|
-
}
|
|
3296
|
-
|
|
3297
3347
|
// dist/banner-facts.js
|
|
3298
3348
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3299
3349
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
@@ -3352,7 +3402,7 @@ var REAL_PROBES = {
|
|
|
3352
3402
|
return void 0;
|
|
3353
3403
|
}
|
|
3354
3404
|
},
|
|
3355
|
-
|
|
3405
|
+
websiteHost: (env) => {
|
|
3356
3406
|
try {
|
|
3357
3407
|
const resolved = resolveControlOrigin(env);
|
|
3358
3408
|
return resolved.source === "default" ? BRAND_URL : new URL(resolved.origin).host;
|
|
@@ -3380,7 +3430,11 @@ function openingBannerContent(projectDir, env = process.env, probes = REAL_PROBE
|
|
|
3380
3430
|
fact("Claude Code", probes.claudeCodeVersion()),
|
|
3381
3431
|
fact("Project", project, name),
|
|
3382
3432
|
fact("Status", status, installed === void 0 ? "new" : "installed"),
|
|
3383
|
-
|
|
3433
|
+
// `Website`, NOT `Plane` (W-3, #868). "Plane" is our internal word for the control
|
|
3434
|
+
// plane; the developer reading this has never heard it, and raw method vocabulary
|
|
3435
|
+
// reaching a client surface is a recorded finding class in this product. The row
|
|
3436
|
+
// answers *which Halfcycle is this*, and an address is the answer they recognise.
|
|
3437
|
+
fact("Website", probes.websiteHost(env))
|
|
3384
3438
|
].filter((f) => f !== void 0);
|
|
3385
3439
|
return {
|
|
3386
3440
|
head: `halfcycle@${name}`,
|
|
@@ -3509,7 +3563,7 @@ ${USAGE}`);
|
|
|
3509
3563
|
const controlOrigin = resolveControlOrigin(process.env);
|
|
3510
3564
|
const serviceUrl = controlOrigin.origin;
|
|
3511
3565
|
if (verbose || controlOrigin.source !== "default") {
|
|
3512
|
-
process.stdout.write(`[halfcycle] Halfcycle
|
|
3566
|
+
process.stdout.write(`[halfcycle] Halfcycle service: ${controlOriginNote(controlOrigin)}
|
|
3513
3567
|
`);
|
|
3514
3568
|
}
|
|
3515
3569
|
const pinned = readPinnedEngagement(targetRepo);
|
|
@@ -3536,7 +3590,7 @@ ${USAGE}`);
|
|
|
3536
3590
|
`);
|
|
3537
3591
|
}
|
|
3538
3592
|
} else if (requestedId !== void 0) {
|
|
3539
|
-
const joined = await joinPinnedEngagement(serviceUrl, requestedId, targetRepo, { assumeYes });
|
|
3593
|
+
const joined = await joinPinnedEngagement(serviceUrl, requestedId, targetRepo, { assumeYes, verbose });
|
|
3540
3594
|
engagementId = joined.engagementId;
|
|
3541
3595
|
actingAccountId = joined.actingAccountId;
|
|
3542
3596
|
credential = {
|
|
@@ -3555,7 +3609,7 @@ ${USAGE}`);
|
|
|
3555
3609
|
`);
|
|
3556
3610
|
}
|
|
3557
3611
|
} else {
|
|
3558
|
-
const created = await createOwnedEngagement(serviceUrl, targetRepo, { assumeYes });
|
|
3612
|
+
const created = await createOwnedEngagement(serviceUrl, targetRepo, { assumeYes, verbose });
|
|
3559
3613
|
engagementId = created.engagementId;
|
|
3560
3614
|
actingAccountId = created.actingAccountId;
|
|
3561
3615
|
credential = {
|
|
@@ -3637,7 +3691,7 @@ ${USAGE}`);
|
|
|
3637
3691
|
const identity = await describeAccount(credential.serviceUrl, credential.token);
|
|
3638
3692
|
const written = result.writtenPaths.length;
|
|
3639
3693
|
const merged = result.mergedPaths.length;
|
|
3640
|
-
process.stdout.write(`[halfcycle] Signed in as ${accountLabel(identity, actingAccountId)}
|
|
3694
|
+
process.stdout.write(`[halfcycle] Signed in as ${accountLabel(identity, actingAccountId, verbose)}
|
|
3641
3695
|
`);
|
|
3642
3696
|
process.stdout.write(`[halfcycle] Found: ${foundLine}
|
|
3643
3697
|
`);
|