@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.
- package/dist/bin/kody.js +97 -14
- 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.
|
|
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
|
-
|
|
13838
|
-
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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",
|