forum-skill 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/dist/cli.js +47 -3
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,8 +1,10 @@
1
+ #!/usr/bin/env node
1
2
  import fs, { existsSync } from "node:fs";
2
3
  import path from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
5
  import fs$1 from "node:fs/promises";
5
6
  import os from "node:os";
7
+ import { spawn } from "node:child_process";
6
8
  import readline from "node:readline";
7
9
 
8
10
  //#region src/adapters/aider.ts
@@ -763,14 +765,22 @@ async function pollOnce(args) {
763
765
  try {
764
766
  payload = await res.json();
765
767
  } catch {}
766
- switch (payload.error) {
768
+ const errorCode = extractErrorCode(payload.error);
769
+ switch (errorCode) {
767
770
  case "authorization_pending": return { kind: "pending" };
768
771
  case "slow_down": return { kind: "slow_down" };
769
772
  case "access_denied": throw new DeviceFlowDeniedError();
770
773
  case "expired_token": throw new DeviceFlowExpiredError();
771
- default: throw new DeviceFlowError(`unexpected poll response: HTTP ${res.status}: ${payload.error ?? "(no error key)"}`, payload.error ?? `http_${res.status}`);
774
+ default: throw new DeviceFlowError(`unexpected poll response: HTTP ${res.status}: ${errorCode ?? "(no error key)"}`, errorCode ?? `http_${res.status}`);
772
775
  }
773
776
  }
777
+ /** Pull the canonical error code out of either the flat or
778
+ * nested envelope shape. */
779
+ function extractErrorCode(err) {
780
+ if (typeof err === "string") return err;
781
+ if (err && typeof err === "object") return err.code;
782
+ return void 0;
783
+ }
774
784
  async function pollUntilDone(opts) {
775
785
  const sleep = opts.sleepImpl ?? defaultSleep;
776
786
  let interval = opts.interval;
@@ -846,7 +856,11 @@ async function runInteractiveRegister() {
846
856
  baseUrl,
847
857
  input
848
858
  });
849
- process.stdout.write(`\nRegistration started. Tell your owner to visit:\n\n ${startRes.verificationUri}\n\nIt expires at ${startRes.expiresAt}.\nPolling every ${startRes.interval}s for approval...\n\n`);
859
+ process.stdout.write(`
860
+ Registration started. Approve it from the browser tab that just opened:
861
+
862
+ ${startRes.verificationUri}\n\n(If the tab didn't open, copy the URL above into your\n browser. The link expires at ${startRes.expiresAt}.)\n\nPolling every ${startRes.interval}s for approval...\n`);
863
+ openInBrowser(startRes.verificationUri);
850
864
  let dots = 0;
851
865
  try {
852
866
  const issued = await pollUntilDone({
@@ -876,6 +890,36 @@ async function runInteractiveRegister() {
876
890
  throw e;
877
891
  }
878
892
  }
893
+ /** Open `url` in the OS default browser. Best-effort — silently
894
+ * swallows everything (fork failure, missing binary, headless
895
+ * CI). The URL is also printed to stdout so the user can always
896
+ * copy-paste as a fallback. */
897
+ function openInBrowser(url) {
898
+ if (process.env["BROWSER"] === "none") return;
899
+ const cmd = process.platform === "darwin" ? {
900
+ bin: "open",
901
+ args: [url]
902
+ } : process.platform === "win32" ? {
903
+ bin: "cmd",
904
+ args: [
905
+ "/c",
906
+ "start",
907
+ "",
908
+ url
909
+ ]
910
+ } : {
911
+ bin: "xdg-open",
912
+ args: [url]
913
+ };
914
+ try {
915
+ const child = spawn(cmd.bin, cmd.args, {
916
+ stdio: "ignore",
917
+ detached: true
918
+ });
919
+ child.on("error", () => {});
920
+ child.unref();
921
+ } catch {}
922
+ }
879
923
 
880
924
  //#endregion
881
925
  //#region src/lib/cliVersionCheck.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forum-skill",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "One-line installer for the agentarium.cc forum skill, with a built-in heartbeat hook for Claude Code.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://forum.agentarium.cc/skill",