copilot-relay 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -140,9 +140,28 @@ copilot-relay 0.2.5
140
140
  models gpt-5.6-sol[1m], claude-opus-5
141
141
  upstream not checked (use --deep)
142
142
  log ~/.copilot-relay/logs/copilot-relay.2026-07-25.log
143
- config ~/.copilot-relay/config.yaml (logLevel=info, thinkEffort=max)
143
+ config ~/.copilot-relay/config.yaml
144
+ host 127.0.0.1
145
+ port 4142
146
+ copilotBaseUrl https://api.githubcopilot.com
147
+ claudeSetup true
148
+ logLevel info
149
+ logRetentionDays 3
150
+ thinkEffort max
151
+ upstreamTimeoutSeconds 180
152
+ webSearchBackend (unset — uses gptModel)
153
+ gptModel gpt-5.6-sol
154
+ opusModel claude-opus-5
155
+ host, port and claudeSetup take effect on restart; the rest hot-reload.
144
156
  ```
145
157
 
158
+ The `config` block is every key `readAppConfig()` resolved, in
159
+ `config.default.yaml` order. These are the values on disk: eight of them reload
160
+ while the relay runs, while `host`, `port` and `claudeSetup` are read once at
161
+ startup — the block says so rather than leaving you to discover it after an
162
+ edit. `--json` emits the same values under `config`, with `webSearchBackend` as
163
+ `null` when unset so the key set stays the same shape either way.
164
+
146
165
  The first line is the CLI you invoked; the `version` row is the build the
147
166
  running daemon reports about itself. They differ after an upgrade that has not
148
167
  been restarted yet — the new CLI is installed, the old process is still
package/dist/main.js CHANGED
@@ -3320,6 +3320,10 @@ const exitCodes = {
3320
3320
  };
3321
3321
  const localProbeTimeoutMs = 5e3;
3322
3322
  const deepProbeTimeoutMs = 6e4;
3323
+ const toStatusConfig = (config) => ({
3324
+ ...config,
3325
+ webSearchBackend: config.webSearchBackend ?? null
3326
+ });
3323
3327
  /**
3324
3328
  * True when the daemon is serving a different build than the invoked CLI.
3325
3329
  *
@@ -3354,13 +3358,58 @@ const formatUptime = (startedAt) => {
3354
3358
  return `${Math.floor(seconds / 86400)}d ${Math.floor(seconds % 86400 / 3600)}h`;
3355
3359
  };
3356
3360
  /**
3361
+ * Every config key with its position in the block, in config.default.yaml order
3362
+ * rather than alphabetical so it reads like the file it was resolved from.
3363
+ *
3364
+ * A Record keyed by StatusConfig rather than an array of keys: an array only
3365
+ * checks that each entry *is* a key, so a twelfth config key would type-check
3366
+ * while silently never appearing in `status` — the exact failure this command
3367
+ * exists to prevent. Keyed this way, adding one fails the build here.
3368
+ */
3369
+ const configRowOrder = {
3370
+ host: 0,
3371
+ port: 1,
3372
+ copilotBaseUrl: 2,
3373
+ claudeSetup: 3,
3374
+ logLevel: 4,
3375
+ logRetentionDays: 5,
3376
+ thinkEffort: 6,
3377
+ upstreamTimeoutSeconds: 7,
3378
+ webSearchBackend: 8,
3379
+ gptModel: 9,
3380
+ opusModel: 10
3381
+ };
3382
+ const configRowKeys = Object.keys(configRowOrder).sort((a, b) => configRowOrder[a] - configRowOrder[b]);
3383
+ /**
3384
+ * The resolved config, one key per line.
3385
+ *
3386
+ * These are the values on disk. That is not the same question as "what is the
3387
+ * running daemon honouring", and the footnote says so rather than leaving it
3388
+ * implied: applyRuntimeConfig() in start.ts hot-reloads eight of these keys,
3389
+ * never reads claudeSetup, and deliberately does not rebind the listening
3390
+ * socket when host or port changes. Printing all eleven without that line
3391
+ * would imply a live daemon had read values it has not.
3392
+ *
3393
+ * Only shown when running, because with nothing up every value applies at the
3394
+ * next start and the note would be noise.
3395
+ */
3396
+ const renderConfig = (config, running) => {
3397
+ const lines = configRowKeys.map((key) => {
3398
+ const value = config[key];
3399
+ const rendered = key === "webSearchBackend" && value === null ? "(unset — uses gptModel)" : String(value);
3400
+ return ` ${key.padEnd(24)}${rendered}`;
3401
+ });
3402
+ if (running) lines.push(" host, port and claudeSetup take effect on restart; the rest hot-reload.");
3403
+ return lines;
3404
+ };
3405
+ /**
3357
3406
  * Pure state-to-lines mapping, kept free of IO so it can be tested directly
3358
3407
  * without spawning a relay or opening a socket.
3359
3408
  */
3360
3409
  const renderStatus = (status$1) => {
3361
3410
  const lines = [`copilot-relay ${status$1.version}`];
3362
3411
  if (!status$1.running) {
3363
- lines.push(" process not running", ` config ${status$1.configPath} (logLevel=${status$1.logLevel}, thinkEffort=${status$1.thinkEffort})`, ` log ${status$1.logPath}`, "", " Start it with: copilot-relay start");
3412
+ lines.push(" process not running", ` log ${status$1.logPath}`, ` config ${status$1.configPath}`, ...renderConfig(status$1.config, false), "", " Start it with: copilot-relay start");
3364
3413
  return lines;
3365
3414
  }
3366
3415
  lines.push(` process running (pid ${status$1.pid}, up ${formatUptime(status$1.startedAt)})`);
@@ -3371,7 +3420,7 @@ const renderStatus = (status$1) => {
3371
3420
  lines.push(status$1.models?.length ? ` models ${status$1.models.join(", ")}` : " models unavailable");
3372
3421
  if (status$1.deep) lines.push(status$1.deep.ok ? ` upstream ok (${status$1.deep.ms}ms) — end-to-end Copilot round trip` : ` upstream FAILED${status$1.deep.detail ? ` — ${status$1.deep.detail}` : ""}`);
3373
3422
  else lines.push(" upstream not checked (use --deep)");
3374
- lines.push(` log ${status$1.logPath}`, ` config ${status$1.configPath} (logLevel=${status$1.logLevel}, thinkEffort=${status$1.thinkEffort})`);
3423
+ lines.push(` log ${status$1.logPath}`, ` config ${status$1.configPath}`, ...renderConfig(status$1.config, true));
3375
3424
  if (status$1.health?.ok && status$1.deep && !status$1.deep.ok) lines.push("", " The relay is listening but cannot reach Copilot.", " Try: copilot-relay auth");
3376
3425
  if (hasVersionMismatch(status$1)) lines.push("", ` The running relay is ${status$1.daemonVersion}; ${status$1.version} is installed.`, " Restart it to serve the installed version: copilot-relay restart");
3377
3426
  return lines;
@@ -3479,6 +3528,7 @@ const collectStatus = async (options) => {
3479
3528
  const appConfig = await readAppConfig();
3480
3529
  setLogLevel(appConfig.logLevel);
3481
3530
  const base = {
3531
+ config: toStatusConfig(appConfig),
3482
3532
  configPath: paths.configPath,
3483
3533
  logLevel: appConfig.logLevel,
3484
3534
  logPath: getLogPath(),