@themoltnet/legreffier 0.26.1 → 0.27.0

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/index.js +78 -20
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1198,7 +1198,9 @@ class MoltNetError extends Error {
1198
1198
  }
1199
1199
  }
1200
1200
  function problemToError(problem, statusCode) {
1201
- return new MoltNetError(problem.title ?? "Request failed", {
1201
+ const title = problem.title ?? "Request failed";
1202
+ const message = problem.detail ? `${title}: ${problem.detail}` : title;
1203
+ return new MoltNetError(message, {
1202
1204
  code: problem.type ?? problem.code ?? "UNKNOWN",
1203
1205
  statusCode,
1204
1206
  detail: problem.detail
@@ -2629,9 +2631,9 @@ function invert$1(number, modulo) {
2629
2631
  let b = modulo;
2630
2632
  let x = _0n$2, u = _1n$3;
2631
2633
  while (a !== _0n$2) {
2632
- const q = b / a;
2634
+ const q2 = b / a;
2633
2635
  const r = b % a;
2634
- const m = x - u * q;
2636
+ const m = x - u * q2;
2635
2637
  b = a, a = r, x = u, u = m;
2636
2638
  }
2637
2639
  const gcd = b;
@@ -3736,8 +3738,8 @@ const invert = (num, md) => {
3736
3738
  err("no inverse n=" + num + " mod=" + md);
3737
3739
  let a = M(num, md), b = md, x = 0n, u = 1n;
3738
3740
  while (a !== 0n) {
3739
- const q = b / a, r = b % a;
3740
- const m = x - u * q;
3741
+ const q2 = b / a, r = b % a;
3742
+ const m = x - u * q2;
3741
3743
  b = a, a = r, x = u, u = m;
3742
3744
  }
3743
3745
  return b === 1n ? M(x, md) : err("no inverse");
@@ -5321,10 +5323,19 @@ const POLL_INTERVAL_MS = 5e3;
5321
5323
  function isProblemDetails(err2) {
5322
5324
  return typeof err2 === "object" && err2 !== null && "title" in err2 && typeof err2.title === "string" && "status" in err2 && typeof err2.status === "number";
5323
5325
  }
5326
+ function isValidationProblemDetails(err2) {
5327
+ return isProblemDetails(err2) && "errors" in err2 && Array.isArray(err2.errors);
5328
+ }
5324
5329
  function toErrorMessage(err2) {
5325
5330
  if (err2 instanceof Error) {
5326
5331
  return err2.message;
5327
5332
  }
5333
+ if (isValidationProblemDetails(err2)) {
5334
+ const base2 = problemToError(err2, err2.status).message;
5335
+ const fieldErrors = err2.errors.map((e) => ` ${e.field}: ${e.message}`).join("\n");
5336
+ return fieldErrors ? `${base2}
5337
+ ${fieldErrors}` : base2;
5338
+ }
5328
5339
  if (isProblemDetails(err2)) {
5329
5340
  return problemToError(err2, err2.status).message;
5330
5341
  }
@@ -5707,21 +5718,10 @@ class CodexAdapter {
5707
5718
  await downloadSkills(repoDir, ".agents/skills");
5708
5719
  }
5709
5720
  /**
5710
- * Write a sourceable env file at `.moltnet/<name>/env` with the OAuth2
5711
- * credentials that Codex needs in the shell environment.
5721
+ * Env file generation moved to shared writeEnvFile in the agentSetup phase.
5722
+ * Codex has no additional settings beyond the env file.
5712
5723
  */
5713
- async writeSettings(opts) {
5714
- const envDir = join(opts.repoDir, ".moltnet", opts.agentName);
5715
- await mkdir(envDir, { recursive: true });
5716
- const q = (v) => `'${v.replace(/'/g, "'\\''")}'`;
5717
- const lines = [
5718
- `${opts.prefix}_CLIENT_ID=${q(opts.clientId)}`,
5719
- `${opts.prefix}_CLIENT_SECRET=${q(opts.clientSecret)}`,
5720
- `${opts.prefix}_GITHUB_APP_ID=${q(opts.appSlug)}`,
5721
- `${opts.prefix}_GITHUB_APP_PRIVATE_KEY_PATH=${q(opts.pemPath)}`,
5722
- `${opts.prefix}_GITHUB_APP_INSTALLATION_ID=${q(opts.installationId)}`
5723
- ];
5724
- await writeFile(join(envDir, "env"), lines.join("\n") + "\n", "utf-8");
5724
+ async writeSettings(_opts) {
5725
5725
  }
5726
5726
  async writeRules(opts) {
5727
5727
  const dir2 = join(opts.repoDir, ".codex", "rules");
@@ -5737,6 +5737,54 @@ const adapters = {
5737
5737
  claude: new ClaudeAdapter(),
5738
5738
  codex: new CodexAdapter()
5739
5739
  };
5740
+ function q(v) {
5741
+ return `'${v.replace(/'/g, "'\\''")}'`;
5742
+ }
5743
+ async function writeEnvFile(opts) {
5744
+ await mkdir(opts.envDir, { recursive: true });
5745
+ const envPath = join(opts.envDir, "env");
5746
+ const managedEntries = [
5747
+ [`${opts.prefix}_CLIENT_ID`, q(opts.clientId)],
5748
+ [`${opts.prefix}_CLIENT_SECRET`, q(opts.clientSecret)],
5749
+ [`${opts.prefix}_GITHUB_APP_ID`, q(opts.appSlug)],
5750
+ [`${opts.prefix}_GITHUB_APP_PRIVATE_KEY_PATH`, q(opts.pemPath)],
5751
+ [`${opts.prefix}_GITHUB_APP_INSTALLATION_ID`, q(opts.installationId)],
5752
+ ["GIT_CONFIG_GLOBAL", q(`.moltnet/${opts.agentName}/gitconfig`)]
5753
+ ];
5754
+ const managedKeys = new Set(managedEntries.map(([k]) => k));
5755
+ let existingLines = [];
5756
+ try {
5757
+ const existing = await readFile(envPath, "utf-8");
5758
+ existingLines = existing.split("\n");
5759
+ } catch {
5760
+ }
5761
+ const outputLines = [];
5762
+ for (const [key, val] of managedEntries) {
5763
+ outputLines.push(`${key}=${val}`);
5764
+ }
5765
+ let seenUserContent = false;
5766
+ for (const line of existingLines) {
5767
+ const trimmed = line.trim();
5768
+ if (trimmed === "") {
5769
+ if (seenUserContent) outputLines.push(line);
5770
+ continue;
5771
+ }
5772
+ if (trimmed.startsWith("#")) {
5773
+ if (!seenUserContent) outputLines.push("");
5774
+ seenUserContent = true;
5775
+ outputLines.push(line);
5776
+ continue;
5777
+ }
5778
+ const eqIdx = trimmed.indexOf("=");
5779
+ if (eqIdx < 1) continue;
5780
+ const key = trimmed.slice(0, eqIdx);
5781
+ if (managedKeys.has(key)) continue;
5782
+ if (!seenUserContent) outputLines.push("");
5783
+ seenUserContent = true;
5784
+ outputLines.push(line);
5785
+ }
5786
+ await writeFile(envPath, outputLines.join("\n") + "\n", "utf-8");
5787
+ }
5740
5788
  function getStatePath(configDir) {
5741
5789
  return join(configDir, "legreffier-init.state.json");
5742
5790
  }
@@ -5831,6 +5879,16 @@ async function runAgentSetupPhase(opts) {
5831
5879
  await adapter.writeSettings(adapterOpts);
5832
5880
  }
5833
5881
  dispatch({ type: "step", key: "settings", status: "done" });
5882
+ await writeEnvFile({
5883
+ envDir: configDir,
5884
+ agentName,
5885
+ prefix,
5886
+ clientId,
5887
+ clientSecret,
5888
+ appSlug,
5889
+ pemPath,
5890
+ installationId
5891
+ });
5834
5892
  await clearState(configDir);
5835
5893
  }
5836
5894
  async function exchangeManifestCode(code) {
@@ -6682,7 +6740,7 @@ function SetupApp({
6682
6740
  setPhase("done");
6683
6741
  setTimeout(() => exit(), 3e3);
6684
6742
  } catch (err2) {
6685
- setError(err2 instanceof Error ? err2.message : String(err2));
6743
+ setError(toErrorMessage(err2));
6686
6744
  setPhase("error");
6687
6745
  setTimeout(() => exit(new Error("Setup failed")), 3e3);
6688
6746
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themoltnet/legreffier",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "LeGreffier — one-command accountable AI agent setup",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -34,9 +34,9 @@
34
34
  "vite": "^6.0.0",
35
35
  "vitest": "^3.0.0",
36
36
  "@moltnet/api-client": "0.1.0",
37
+ "@themoltnet/sdk": "0.83.1",
37
38
  "@themoltnet/design-system": "0.3.0",
38
- "@moltnet/crypto-service": "0.1.0",
39
- "@themoltnet/sdk": "0.79.0"
39
+ "@moltnet/crypto-service": "0.1.0"
40
40
  },
41
41
  "scripts": {
42
42
  "dev": "vite build --watch",
@@ -44,6 +44,6 @@
44
44
  "typecheck": "tsc -b --emitDeclarationOnly && tsc -b tsconfig.test.json --force",
45
45
  "test": "vitest run --passWithNoTests",
46
46
  "lint": "eslint src/",
47
- "check:pack": "tsx ../../scripts/check-pack.ts --package ."
47
+ "check:pack": "tsx ../../tools/src/check-pack.ts --package ."
48
48
  }
49
49
  }