halfcycle 0.3.13 → 0.3.15
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 +60 -7
- package/dist/banner.d.ts.map +1 -1
- package/dist/bin.js +315 -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,286 @@ 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
|
+
/** `--console-accent` (`#19d3ff`) — the console's own accent, cyan being its ANSI seat. */
|
|
2298
|
+
accent: "36",
|
|
2299
|
+
/** `--good` — the console's affirmative. */
|
|
2300
|
+
good: "32",
|
|
2301
|
+
/** `--bad` — the console's negative. */
|
|
2302
|
+
bad: "31"
|
|
2303
|
+
};
|
|
2304
|
+
var SWATCH_SGR = [
|
|
2305
|
+
INK.dim,
|
|
2306
|
+
INK.faint,
|
|
2307
|
+
INK.key,
|
|
2308
|
+
INK.keyBold,
|
|
2309
|
+
INK.accent,
|
|
2310
|
+
INK.good,
|
|
2311
|
+
INK.bad
|
|
2312
|
+
];
|
|
2313
|
+
var ESC = "\x1B";
|
|
2314
|
+
var RESET = `${ESC}[0m`;
|
|
2315
|
+
function paint(segments, colour) {
|
|
2316
|
+
return segments.map((s) => colour && s.sgr !== "" ? `${ESC}[${s.sgr}m${s.text}${RESET}` : s.text).join("");
|
|
2317
|
+
}
|
|
2318
|
+
function ink(name, text, colour) {
|
|
2319
|
+
const sgr = INK[name];
|
|
2320
|
+
return colour && sgr !== "" ? `${ESC}[${sgr}m${text}${RESET}` : text;
|
|
2321
|
+
}
|
|
2322
|
+
var GAP = 4;
|
|
2323
|
+
var FULL_LAYOUT = { art: MARK_FULL, label: 13, rule: 28, palette: true, minColumns: 76 };
|
|
2324
|
+
var NARROW_LAYOUT = { art: MARK_NARROW, label: 10, rule: 20, palette: false, minColumns: 48 };
|
|
2325
|
+
var DEFAULT_COLUMNS = 80;
|
|
2326
|
+
function usableColumns(environment) {
|
|
2327
|
+
const columns = environment.columns;
|
|
2328
|
+
return columns !== void 0 && columns > 0 ? columns : DEFAULT_COLUMNS;
|
|
2329
|
+
}
|
|
2330
|
+
function isSet(value) {
|
|
2331
|
+
return value !== void 0 && value !== "";
|
|
2332
|
+
}
|
|
2333
|
+
function plainTextRequested(env) {
|
|
2334
|
+
return isSet(env["NO_COLOR"]) || env["TERM"] === "dumb";
|
|
2335
|
+
}
|
|
2336
|
+
function decideCut(environment = {}) {
|
|
2337
|
+
const env = environment.env ?? {};
|
|
2338
|
+
if (environment.quiet === true)
|
|
2339
|
+
return "none";
|
|
2340
|
+
if (environment.isTTY !== true)
|
|
2341
|
+
return "line";
|
|
2342
|
+
if (plainTextRequested(env))
|
|
2343
|
+
return "line";
|
|
2344
|
+
const columns = usableColumns(environment);
|
|
2345
|
+
if (columns >= FULL_LAYOUT.minColumns)
|
|
2346
|
+
return "full";
|
|
2347
|
+
if (columns >= NARROW_LAYOUT.minColumns)
|
|
2348
|
+
return "narrow";
|
|
2349
|
+
return "line";
|
|
2350
|
+
}
|
|
2351
|
+
function decideColour(environment = {}) {
|
|
2352
|
+
const env = environment.env ?? {};
|
|
2353
|
+
const force = env["FORCE_COLOR"];
|
|
2354
|
+
if (isSet(force))
|
|
2355
|
+
return force !== "0";
|
|
2356
|
+
if (plainTextRequested(env))
|
|
2357
|
+
return false;
|
|
2358
|
+
return environment.isTTY === true;
|
|
2359
|
+
}
|
|
2360
|
+
function decideUnicode(environment = {}) {
|
|
2361
|
+
const env = environment.env ?? {};
|
|
2362
|
+
if ((environment.platform ?? "") !== "win32") {
|
|
2363
|
+
const locale = env["LC_ALL"] ?? env["LC_CTYPE"] ?? env["LANG"] ?? "";
|
|
2364
|
+
return locale === "" || /utf-?8/i.test(locale);
|
|
2365
|
+
}
|
|
2366
|
+
return isSet(env["WT_SESSION"]) || isSet(env["TERMINUS_SUBLIME"]) || env["ConEmuTask"] === "{cmd::Cmder}" || env["TERM_PROGRAM"] === "vscode";
|
|
2367
|
+
}
|
|
2368
|
+
function padEnd(text, width) {
|
|
2369
|
+
return text + " ".repeat(Math.max(0, width - text.length));
|
|
2370
|
+
}
|
|
2371
|
+
function clip(text, width) {
|
|
2372
|
+
if (width < 8 || text.length <= width)
|
|
2373
|
+
return text;
|
|
2374
|
+
return `${text.slice(0, width - 3)}...`;
|
|
2375
|
+
}
|
|
2376
|
+
function paletteRow(swatch) {
|
|
2377
|
+
const row = [];
|
|
2378
|
+
SWATCH_SGR.forEach((sgr, i) => {
|
|
2379
|
+
if (i > 0)
|
|
2380
|
+
row.push({ text: " ", sgr: INK.plain });
|
|
2381
|
+
row.push({ text: swatch.repeat(2), sgr });
|
|
2382
|
+
});
|
|
2383
|
+
return row;
|
|
2384
|
+
}
|
|
2385
|
+
function factColumn(content, layout, glyphs, text, valueWidth) {
|
|
2386
|
+
const rows = [];
|
|
2387
|
+
const head = text(content.head);
|
|
2388
|
+
const at = head.indexOf("@");
|
|
2389
|
+
rows.push(at < 0 ? [{ text: head, sgr: INK.keyBold }] : [
|
|
2390
|
+
{ text: head.slice(0, at), sgr: INK.keyBold },
|
|
2391
|
+
{ text: "@", sgr: INK.dim },
|
|
2392
|
+
{ text: head.slice(at + 1), sgr: INK.bold }
|
|
2393
|
+
]);
|
|
2394
|
+
rows.push([{ text: glyphs.rule.repeat(layout.rule), sgr: INK.dim }]);
|
|
2395
|
+
const narrow = layout.art === MARK_NARROW;
|
|
2396
|
+
for (const fact2 of content.facts) {
|
|
2397
|
+
const raw = narrow ? fact2.narrow : fact2.value;
|
|
2398
|
+
if (raw === void 0)
|
|
2399
|
+
continue;
|
|
2400
|
+
rows.push([
|
|
2401
|
+
{ text: padEnd(`${text(fact2.label)}:`, layout.label), sgr: INK.key },
|
|
2402
|
+
{ text: clip(text(raw), valueWidth), sgr: INK.plain }
|
|
2403
|
+
]);
|
|
2404
|
+
}
|
|
2405
|
+
if (layout.palette) {
|
|
2406
|
+
rows.push([]);
|
|
2407
|
+
rows.push(paletteRow(glyphs.swatch));
|
|
2408
|
+
}
|
|
2409
|
+
return rows;
|
|
2410
|
+
}
|
|
2411
|
+
var MARGIN = 2;
|
|
2412
|
+
function lastSentenceStart(line) {
|
|
2413
|
+
const at = line.lastIndexOf(". ");
|
|
2414
|
+
return at < 0 ? 0 : at + 2;
|
|
2415
|
+
}
|
|
2416
|
+
function taglineRow(line, first, last) {
|
|
2417
|
+
const indent = { text: " ", sgr: INK.plain };
|
|
2418
|
+
if (first)
|
|
2419
|
+
return [indent, { text: line, sgr: INK.keyBold }];
|
|
2420
|
+
if (!last)
|
|
2421
|
+
return [indent, { text: line, sgr: INK.dim }];
|
|
2422
|
+
const at = lastSentenceStart(line);
|
|
2423
|
+
if (at === 0)
|
|
2424
|
+
return [indent, { text: line, sgr: INK.key }];
|
|
2425
|
+
return [
|
|
2426
|
+
indent,
|
|
2427
|
+
{ text: line.slice(0, at), sgr: INK.dim },
|
|
2428
|
+
{ text: line.slice(at), sgr: INK.key }
|
|
2429
|
+
];
|
|
2430
|
+
}
|
|
2431
|
+
function renderBlock(content, layout, environment) {
|
|
2432
|
+
const unicode = decideUnicode(environment);
|
|
2433
|
+
const colour = decideColour(environment);
|
|
2434
|
+
const glyphs = unicode ? UNICODE_GLYPHS : ASCII_GLYPHS;
|
|
2435
|
+
const text = (raw) => unicode ? raw : toAscii(raw);
|
|
2436
|
+
const art = layout.art;
|
|
2437
|
+
const valueWidth = usableColumns(environment) - (art.width + GAP + layout.label);
|
|
2438
|
+
const right = factColumn(content, layout, glyphs, text, valueWidth);
|
|
2439
|
+
const top = Math.max(0, Math.floor((art.lines.length - right.length) / 2));
|
|
2440
|
+
const height = Math.max(art.lines.length, right.length + top);
|
|
2441
|
+
const lines = Array.from({ length: MARGIN }, () => []);
|
|
2442
|
+
for (let i = 0; i < height; i++) {
|
|
2443
|
+
const artLine = art.lines[i] ?? "";
|
|
2444
|
+
const segments = [];
|
|
2445
|
+
if (artLine.length > 0) {
|
|
2446
|
+
segments.push({ text: artLine, sgr: i < art.discRows ? INK.plain : INK.dim });
|
|
2447
|
+
}
|
|
2448
|
+
const rightRow = right[i - top];
|
|
2449
|
+
if (rightRow !== void 0 && rightRow.length > 0) {
|
|
2450
|
+
segments.push({ text: " ".repeat(Math.max(0, art.width + GAP - artLine.length)), sgr: INK.plain });
|
|
2451
|
+
segments.push(...rightRow);
|
|
2452
|
+
}
|
|
2453
|
+
lines.push(segments);
|
|
2454
|
+
}
|
|
2455
|
+
const tagline = layout.art === MARK_NARROW ? content.tagNarrow ?? content.tag : content.tag;
|
|
2456
|
+
lines.push([]);
|
|
2457
|
+
tagline.forEach((line, i) => {
|
|
2458
|
+
lines.push(taglineRow(text(line), i === 0, i === tagline.length - 1));
|
|
2459
|
+
});
|
|
2460
|
+
for (let i = 0; i < MARGIN; i++)
|
|
2461
|
+
lines.push([]);
|
|
2462
|
+
return lines.map((segments) => paint(segments, colour)).join("\n");
|
|
2463
|
+
}
|
|
2464
|
+
function renderLine(content, environment) {
|
|
2465
|
+
const unicode = decideUnicode(environment);
|
|
2466
|
+
const dot = unicode ? UNICODE_GLYPHS.dot : ASCII_GLYPHS.dot;
|
|
2467
|
+
const named = content.version === "" ? "Halfcycle" : `Halfcycle v${content.version}`;
|
|
2468
|
+
const raw = `${named} ${dot} ${content.url}`;
|
|
2469
|
+
return unicode ? raw : toAscii(raw);
|
|
2470
|
+
}
|
|
2471
|
+
function renderBanner(content, environment = {}) {
|
|
2472
|
+
switch (decideCut(environment)) {
|
|
2473
|
+
case "none":
|
|
2474
|
+
return "";
|
|
2475
|
+
case "line":
|
|
2476
|
+
return renderLine(content, environment);
|
|
2477
|
+
case "narrow":
|
|
2478
|
+
return renderBlock(content, NARROW_LAYOUT, environment);
|
|
2479
|
+
case "full":
|
|
2480
|
+
return renderBlock(content, FULL_LAYOUT, environment);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
function printBanner(sink, content, environment = {}) {
|
|
2484
|
+
const text = renderBanner(content, environment);
|
|
2485
|
+
if (text === "")
|
|
2486
|
+
return;
|
|
2487
|
+
sink.write(`${text}
|
|
2488
|
+
`);
|
|
2489
|
+
}
|
|
2490
|
+
function currentEnvironment(quiet2) {
|
|
2491
|
+
return {
|
|
2492
|
+
columns: process.stdout.columns,
|
|
2493
|
+
isTTY: process.stdout.isTTY === true,
|
|
2494
|
+
quiet: quiet2,
|
|
2495
|
+
env: process.env,
|
|
2496
|
+
platform: process.platform
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
// dist/confirm-identity.js
|
|
2227
2501
|
var IDENTITY_TIMEOUT_MS = 5e3;
|
|
2228
2502
|
var IDENTITY_DECLINED = "identity-declined";
|
|
2229
2503
|
async function describeAccount(serviceUrl, credential, fetchImpl = fetch) {
|
|
@@ -2245,14 +2519,14 @@ async function describeAccount(serviceUrl, credential, fetchImpl = fetch) {
|
|
|
2245
2519
|
clearTimeout(timer);
|
|
2246
2520
|
}
|
|
2247
2521
|
}
|
|
2248
|
-
function accountLabel(identity, storedAccountId) {
|
|
2522
|
+
function accountLabel(identity, storedAccountId, verbose2 = false) {
|
|
2249
2523
|
const accountId = identity?.accountId ?? storedAccountId;
|
|
2250
2524
|
if (identity?.email !== void 0 && identity.email.trim() !== "") {
|
|
2251
|
-
return accountId !== void 0 ? `${identity.email} (account ${accountId})` : identity.email;
|
|
2525
|
+
return verbose2 && accountId !== void 0 ? `${identity.email} (account ${accountId})` : identity.email;
|
|
2252
2526
|
}
|
|
2253
2527
|
if (accountId !== void 0)
|
|
2254
2528
|
return `account ${accountId} (no email on record for it)`;
|
|
2255
|
-
return "the account this credential belongs to, which this
|
|
2529
|
+
return "the account this credential belongs to, which this service did not name";
|
|
2256
2530
|
}
|
|
2257
2531
|
function onlyDate(iso) {
|
|
2258
2532
|
if (iso === void 0)
|
|
@@ -2263,10 +2537,10 @@ function onlyDate(iso) {
|
|
|
2263
2537
|
function actClause(act) {
|
|
2264
2538
|
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
2539
|
}
|
|
2266
|
-
async function defaultAsk(
|
|
2540
|
+
async function defaultAsk(question2) {
|
|
2267
2541
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2268
2542
|
try {
|
|
2269
|
-
return await rl.question(
|
|
2543
|
+
return await rl.question(question2);
|
|
2270
2544
|
} finally {
|
|
2271
2545
|
rl.close();
|
|
2272
2546
|
process.stdin.pause();
|
|
@@ -2284,7 +2558,10 @@ function actingAs(credential, identity) {
|
|
|
2284
2558
|
const accountId = identity?.accountId ?? credential.accountId;
|
|
2285
2559
|
return accountId === void 0 ? credential : { ...credential, accountId };
|
|
2286
2560
|
}
|
|
2287
|
-
function
|
|
2561
|
+
function question(colour) {
|
|
2562
|
+
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: `;
|
|
2563
|
+
}
|
|
2564
|
+
function armScript(credential, act, label, plainLabel, home) {
|
|
2288
2565
|
switch (credential.source) {
|
|
2289
2566
|
case "browser-handoff":
|
|
2290
2567
|
return {
|
|
@@ -2310,7 +2587,7 @@ function armScript(credential, act, label, home) {
|
|
|
2310
2587
|
noTerminalNote: "",
|
|
2311
2588
|
switchOpening: `[halfcycle] Signing you in through your browser \u2014 this install will use that account instead.
|
|
2312
2589
|
`,
|
|
2313
|
-
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. HALFCYCLE_TOKEN in this environment is the credential for ${
|
|
2590
|
+
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
2591
|
// The switch is real for THIS run (the new credential is what gets used) and it
|
|
2315
2592
|
// does not persist: `obtainCredential` reads the variable first, so the next run
|
|
2316
2593
|
// is the same variable again. Said here rather than discovered tomorrow.
|
|
@@ -2336,7 +2613,7 @@ function armScript(credential, act, label, home) {
|
|
|
2336
2613
|
`,
|
|
2337
2614
|
switchOpening: `[halfcycle] Forgetting this machine's saved sign-in and signing you in through your browser.
|
|
2338
2615
|
`,
|
|
2339
|
-
stopRemedy: `Stopped before anything was created \u2014 nothing was created and nothing was written. This machine's saved sign-in is for ${
|
|
2616
|
+
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
2617
|
afterSwitch: ""
|
|
2341
2618
|
};
|
|
2342
2619
|
}
|
|
@@ -2344,10 +2621,12 @@ function armScript(credential, act, label, home) {
|
|
|
2344
2621
|
}
|
|
2345
2622
|
async function confirmActingIdentity(serviceUrl, credential, act, deps = {}) {
|
|
2346
2623
|
const write = deps.write ?? ((text) => process.stdout.write(text));
|
|
2624
|
+
const colour = deps.colour ?? decideColour({ isTTY: process.stdout.isTTY === true, env: deps.env ?? process.env });
|
|
2347
2625
|
const identity = await describeAccount(serviceUrl, credential.credential, deps.fetchImpl);
|
|
2348
|
-
const
|
|
2626
|
+
const plainLabel = accountLabel(identity, credential.accountId, deps.verbose === true);
|
|
2627
|
+
const label = ink("keyBold", plainLabel, colour);
|
|
2349
2628
|
const acting = actingAs(credential, identity);
|
|
2350
|
-
const script = armScript(credential, act, label, deps.home);
|
|
2629
|
+
const script = armScript(credential, act, label, plainLabel, deps.home);
|
|
2351
2630
|
write(script.preamble);
|
|
2352
2631
|
if (!script.asks)
|
|
2353
2632
|
return acting;
|
|
@@ -2363,14 +2642,15 @@ async function confirmActingIdentity(serviceUrl, credential, act, deps = {}) {
|
|
|
2363
2642
|
return acting;
|
|
2364
2643
|
}
|
|
2365
2644
|
const ask = deps.ask ?? defaultAsk;
|
|
2366
|
-
|
|
2645
|
+
write("\n");
|
|
2646
|
+
const decision = readDecision(await ask(question(colour)));
|
|
2367
2647
|
if (decision === "proceed")
|
|
2368
2648
|
return acting;
|
|
2369
2649
|
if (decision === "switch-account") {
|
|
2370
2650
|
write(script.switchOpening);
|
|
2371
2651
|
const replacement = await switchAccount(serviceUrl, deps);
|
|
2372
2652
|
const replacementIdentity = await describeAccount(serviceUrl, replacement.credential, deps.fetchImpl);
|
|
2373
|
-
write(`[halfcycle] Signed in as ${accountLabel(replacementIdentity, replacement.accountId)}. This install will ${actClause(act)}.
|
|
2653
|
+
write(`[halfcycle] Signed in as ${ink("keyBold", accountLabel(replacementIdentity, replacement.accountId, deps.verbose === true), colour)}. This install will ${actClause(act)}.
|
|
2374
2654
|
`);
|
|
2375
2655
|
if (script.afterSwitch !== "")
|
|
2376
2656
|
write(script.afterSwitch);
|
|
@@ -2882,7 +3162,7 @@ async function openPhase(credential, phase, entry) {
|
|
|
2882
3162
|
body: JSON.stringify({ phase, entry })
|
|
2883
3163
|
});
|
|
2884
3164
|
} catch (err) {
|
|
2885
|
-
throw new Error(`[halfcycle] Could not reach the Halfcycle
|
|
3165
|
+
throw new Error(`[halfcycle] Could not reach the Halfcycle service at ${url}: ${err instanceof Error ? err.message : String(err)}. No phase was opened.`);
|
|
2886
3166
|
}
|
|
2887
3167
|
if (!res.ok) {
|
|
2888
3168
|
const body2 = await res.json().catch(() => null);
|
|
@@ -2935,7 +3215,7 @@ async function closePhase(credential, phase, outcome, close) {
|
|
|
2935
3215
|
body: JSON.stringify({ phase, acceptanceOutcome: outcome, close })
|
|
2936
3216
|
});
|
|
2937
3217
|
} catch (err) {
|
|
2938
|
-
throw new Error(`[halfcycle] Could not reach the Halfcycle
|
|
3218
|
+
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
3219
|
}
|
|
2940
3220
|
if (!res.ok) {
|
|
2941
3221
|
const body2 = await res.json().catch(() => null);
|
|
@@ -3066,234 +3346,6 @@ var PLACEHOLDERS = {
|
|
|
3066
3346
|
"--evidence": '"\u2026"'
|
|
3067
3347
|
};
|
|
3068
3348
|
|
|
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
3349
|
// dist/banner-facts.js
|
|
3298
3350
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3299
3351
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
@@ -3352,7 +3404,7 @@ var REAL_PROBES = {
|
|
|
3352
3404
|
return void 0;
|
|
3353
3405
|
}
|
|
3354
3406
|
},
|
|
3355
|
-
|
|
3407
|
+
websiteHost: (env) => {
|
|
3356
3408
|
try {
|
|
3357
3409
|
const resolved = resolveControlOrigin(env);
|
|
3358
3410
|
return resolved.source === "default" ? BRAND_URL : new URL(resolved.origin).host;
|
|
@@ -3380,7 +3432,11 @@ function openingBannerContent(projectDir, env = process.env, probes = REAL_PROBE
|
|
|
3380
3432
|
fact("Claude Code", probes.claudeCodeVersion()),
|
|
3381
3433
|
fact("Project", project, name),
|
|
3382
3434
|
fact("Status", status, installed === void 0 ? "new" : "installed"),
|
|
3383
|
-
|
|
3435
|
+
// `Website`, NOT `Plane` (W-3, #868). "Plane" is our internal word for the control
|
|
3436
|
+
// plane; the developer reading this has never heard it, and raw method vocabulary
|
|
3437
|
+
// reaching a client surface is a recorded finding class in this product. The row
|
|
3438
|
+
// answers *which Halfcycle is this*, and an address is the answer they recognise.
|
|
3439
|
+
fact("Website", probes.websiteHost(env))
|
|
3384
3440
|
].filter((f) => f !== void 0);
|
|
3385
3441
|
return {
|
|
3386
3442
|
head: `halfcycle@${name}`,
|
|
@@ -3509,7 +3565,7 @@ ${USAGE}`);
|
|
|
3509
3565
|
const controlOrigin = resolveControlOrigin(process.env);
|
|
3510
3566
|
const serviceUrl = controlOrigin.origin;
|
|
3511
3567
|
if (verbose || controlOrigin.source !== "default") {
|
|
3512
|
-
process.stdout.write(`[halfcycle] Halfcycle
|
|
3568
|
+
process.stdout.write(`[halfcycle] Halfcycle service: ${controlOriginNote(controlOrigin)}
|
|
3513
3569
|
`);
|
|
3514
3570
|
}
|
|
3515
3571
|
const pinned = readPinnedEngagement(targetRepo);
|
|
@@ -3536,7 +3592,7 @@ ${USAGE}`);
|
|
|
3536
3592
|
`);
|
|
3537
3593
|
}
|
|
3538
3594
|
} else if (requestedId !== void 0) {
|
|
3539
|
-
const joined = await joinPinnedEngagement(serviceUrl, requestedId, targetRepo, { assumeYes });
|
|
3595
|
+
const joined = await joinPinnedEngagement(serviceUrl, requestedId, targetRepo, { assumeYes, verbose });
|
|
3540
3596
|
engagementId = joined.engagementId;
|
|
3541
3597
|
actingAccountId = joined.actingAccountId;
|
|
3542
3598
|
credential = {
|
|
@@ -3555,7 +3611,7 @@ ${USAGE}`);
|
|
|
3555
3611
|
`);
|
|
3556
3612
|
}
|
|
3557
3613
|
} else {
|
|
3558
|
-
const created = await createOwnedEngagement(serviceUrl, targetRepo, { assumeYes });
|
|
3614
|
+
const created = await createOwnedEngagement(serviceUrl, targetRepo, { assumeYes, verbose });
|
|
3559
3615
|
engagementId = created.engagementId;
|
|
3560
3616
|
actingAccountId = created.actingAccountId;
|
|
3561
3617
|
credential = {
|
|
@@ -3637,7 +3693,7 @@ ${USAGE}`);
|
|
|
3637
3693
|
const identity = await describeAccount(credential.serviceUrl, credential.token);
|
|
3638
3694
|
const written = result.writtenPaths.length;
|
|
3639
3695
|
const merged = result.mergedPaths.length;
|
|
3640
|
-
process.stdout.write(`[halfcycle] Signed in as ${accountLabel(identity, actingAccountId)}
|
|
3696
|
+
process.stdout.write(`[halfcycle] Signed in as ${accountLabel(identity, actingAccountId, verbose)}
|
|
3641
3697
|
`);
|
|
3642
3698
|
process.stdout.write(`[halfcycle] Found: ${foundLine}
|
|
3643
3699
|
`);
|