@kody-ade/kody-engine 0.4.149 → 0.4.150

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/bin/kody.js +97 -14
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -1061,7 +1061,7 @@ var init_loadPriorArt = __esm({
1061
1061
  // package.json
1062
1062
  var package_default = {
1063
1063
  name: "@kody-ade/kody-engine",
1064
- version: "0.4.149",
1064
+ version: "0.4.150",
1065
1065
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
1066
1066
  license: "MIT",
1067
1067
  type: "module",
@@ -2703,6 +2703,76 @@ import { execFileSync as execFileSync29 } from "child_process";
2703
2703
  import * as fs41 from "fs";
2704
2704
  import * as path37 from "path";
2705
2705
 
2706
+ // src/app-auth.ts
2707
+ import { createSign } from "crypto";
2708
+ var GH_API = process.env.GITHUB_API_URL || "https://api.github.com";
2709
+ function b64url(input) {
2710
+ return Buffer.from(input).toString("base64url");
2711
+ }
2712
+ function normalizePem(key) {
2713
+ const trimmed = key.trim();
2714
+ if (trimmed.includes("BEGIN")) return trimmed;
2715
+ try {
2716
+ const decoded = Buffer.from(trimmed, "base64").toString("utf8");
2717
+ if (decoded.includes("BEGIN")) return decoded;
2718
+ } catch {
2719
+ }
2720
+ return trimmed;
2721
+ }
2722
+ function buildAppJwt(appId, privateKeyPem) {
2723
+ const now = Math.floor(Date.now() / 1e3);
2724
+ const header = { alg: "RS256", typ: "JWT" };
2725
+ const payload = { iat: now - 60, exp: now + 9 * 60, iss: appId };
2726
+ const signingInput = `${b64url(JSON.stringify(header))}.${b64url(JSON.stringify(payload))}`;
2727
+ const signer = createSign("RSA-SHA256");
2728
+ signer.update(signingInput);
2729
+ signer.end();
2730
+ const signature = signer.sign(normalizePem(privateKeyPem)).toString("base64url");
2731
+ return `${signingInput}.${signature}`;
2732
+ }
2733
+ async function ghApp(jwt, apiPath, method = "GET") {
2734
+ const res = await fetch(`${GH_API}${apiPath}`, {
2735
+ method,
2736
+ headers: {
2737
+ Authorization: `Bearer ${jwt}`,
2738
+ Accept: "application/vnd.github+json",
2739
+ "X-GitHub-Api-Version": "2022-11-28",
2740
+ "User-Agent": "kody-engine"
2741
+ }
2742
+ });
2743
+ if (!res.ok) {
2744
+ const body = await res.text().catch(() => "");
2745
+ throw new Error(
2746
+ `GitHub App API ${method} ${apiPath} \u2192 ${res.status} ${res.statusText}${body ? `: ${body.slice(0, 200)}` : ""}`
2747
+ );
2748
+ }
2749
+ return await res.json();
2750
+ }
2751
+ function readAppCreds(env = process.env) {
2752
+ const appId = env.KODY_APP_ID?.trim();
2753
+ const privateKey = env.KODY_APP_PRIVATE_KEY;
2754
+ if (!appId || !privateKey) return null;
2755
+ return {
2756
+ appId,
2757
+ privateKey,
2758
+ installationId: env.KODY_APP_INSTALLATION_ID?.trim() || void 0,
2759
+ repo: env.GITHUB_REPOSITORY?.trim() || void 0
2760
+ };
2761
+ }
2762
+ async function mintAppInstallationToken(creds) {
2763
+ const jwt = buildAppJwt(creds.appId, creds.privateKey);
2764
+ let installationId = creds.installationId;
2765
+ if (!installationId) {
2766
+ if (!creds.repo) {
2767
+ throw new Error("cannot resolve App installation: no KODY_APP_INSTALLATION_ID and no GITHUB_REPOSITORY");
2768
+ }
2769
+ const inst = await ghApp(jwt, `/repos/${creds.repo}/installation`);
2770
+ installationId = String(inst.id);
2771
+ }
2772
+ const tok = await ghApp(jwt, `/app/installations/${installationId}/access_tokens`, "POST");
2773
+ return tok.token;
2774
+ }
2775
+
2706
2776
  // src/dispatch.ts
2707
2777
  import * as fs12 from "fs";
2708
2778
 
@@ -3029,9 +3099,6 @@ function coerceBare(spec, value) {
3029
3099
  return value;
3030
3100
  }
3031
3101
 
3032
- // src/kody-cli.ts
3033
- init_issue();
3034
-
3035
3102
  // src/executor.ts
3036
3103
  import { execFileSync as execFileSync28, spawn as spawn9 } from "child_process";
3037
3104
  import * as fs40 from "fs";
@@ -13821,7 +13888,7 @@ function unpackAllSecrets(env = process.env) {
13821
13888
  }
13822
13889
  return count;
13823
13890
  }
13824
- function resolveAuthToken(env = process.env) {
13891
+ async function resolveAuthToken(env = process.env) {
13825
13892
  const sources = [
13826
13893
  ["KODY_TOKEN", env.KODY_TOKEN],
13827
13894
  ["GH_TOKEN", env.GH_TOKEN],
@@ -13834,10 +13901,24 @@ function resolveAuthToken(env = process.env) {
13834
13901
  if (token) {
13835
13902
  process.stdout.write(`\u2192 kody: GH_TOKEN sourced from env.${picked[0]}
13836
13903
  `);
13837
- } else {
13838
- process.stdout.write("\u2192 kody: WARNING no auth token found (KODY_TOKEN/GH_TOKEN/GITHUB_TOKEN/GH_PAT all empty)\n");
13904
+ return token;
13905
+ }
13906
+ const creds = readAppCreds(env);
13907
+ if (creds) {
13908
+ try {
13909
+ const minted = await mintAppInstallationToken(creds);
13910
+ env.GH_TOKEN = minted;
13911
+ process.stdout.write("\u2192 kody: GH_TOKEN minted from GitHub App (KODY_APP_ID/KODY_APP_PRIVATE_KEY)\n");
13912
+ return minted;
13913
+ } catch (err) {
13914
+ process.stdout.write(`\u2192 kody: WARNING GitHub App token mint failed: ${err.message}
13915
+ `);
13916
+ }
13839
13917
  }
13840
- return token;
13918
+ process.stdout.write(
13919
+ "\u2192 kody: WARNING no auth token found (KODY_TOKEN/GH_TOKEN/GITHUB_TOKEN/GH_PAT/GitHub App all empty)\n"
13920
+ );
13921
+ return void 0;
13841
13922
  }
13842
13923
  function detectPackageManager2(cwd) {
13843
13924
  if (fs41.existsSync(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
@@ -13986,7 +14067,7 @@ async function runCi(argv) {
13986
14067
  if (outcome.kind === "unrecognized") {
13987
14068
  try {
13988
14069
  unpackAllSecrets();
13989
- resolveAuthToken();
14070
+ await resolveAuthToken();
13990
14071
  } catch {
13991
14072
  }
13992
14073
  const tokenLabel = outcome.token ? `\`${outcome.token}\`` : "an empty subcommand";
@@ -14003,8 +14084,10 @@ async function runCi(argv) {
14003
14084
  if (outcome.isPr) postPrReviewComment(outcome.target, body, cwd);
14004
14085
  else postIssueComment(outcome.target, body, cwd);
14005
14086
  } catch (err) {
14006
- process.stderr.write(`[kody] dispatch: failed to post unrecognized-token feedback: ${err instanceof Error ? err.message : String(err)}
14007
- `);
14087
+ process.stderr.write(
14088
+ `[kody] dispatch: failed to post unrecognized-token feedback: ${err instanceof Error ? err.message : String(err)}
14089
+ `
14090
+ );
14008
14091
  }
14009
14092
  process.stdout.write(
14010
14093
  `\u2192 kody: unrecognized subcommand "${outcome.token}" on #${outcome.target} \u2014 feedback comment attempt finished, exiting cleanly
@@ -14039,7 +14122,7 @@ ${CI_HELP}`);
14039
14122
  const n = unpackAllSecrets();
14040
14123
  if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
14041
14124
  `);
14042
- resolveAuthToken();
14125
+ await resolveAuthToken();
14043
14126
  reactToTriggerComment(cwd);
14044
14127
  const pm = args.packageManager ?? detectPackageManager2(cwd);
14045
14128
  process.stdout.write(`\u2192 kody: package manager = ${pm}
@@ -14112,7 +14195,7 @@ async function runScheduledFanOut(cwd, args, opts) {
14112
14195
  const n = unpackAllSecrets();
14113
14196
  if (n > 0) process.stdout.write(`\u2192 kody: unpacked ${n} secret(s) from ALL_SECRETS
14114
14197
  `);
14115
- resolveAuthToken();
14198
+ await resolveAuthToken();
14116
14199
  const pm = args.packageManager ?? detectPackageManager2(cwd);
14117
14200
  process.stdout.write(`\u2192 kody: package manager = ${pm}
14118
14201
  `);
@@ -14285,7 +14368,7 @@ ${CHAT_HELP}`);
14285
14368
  process.stdout.write(`\u2192 kody: unpacked ${unpackedSecrets} secret(s) from ALL_SECRETS
14286
14369
  `);
14287
14370
  }
14288
- resolveAuthToken();
14371
+ await resolveAuthToken();
14289
14372
  configureGitIdentity(cwd);
14290
14373
  const config = tryLoadConfig(cwd);
14291
14374
  const modelSpec = args.model ?? config?.agent.model ?? DEFAULT_MODEL;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.149",
3
+ "version": "0.4.150",
4
4
  "description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
5
5
  "license": "MIT",
6
6
  "type": "module",