@kody-ade/kody-engine 0.4.304 → 0.4.305

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 +192 -168
  2. package/package.json +1 -1
package/dist/bin/kody.js CHANGED
@@ -15,7 +15,7 @@ var init_package = __esm({
15
15
  "package.json"() {
16
16
  package_default = {
17
17
  name: "@kody-ade/kody-engine",
18
- version: "0.4.304",
18
+ version: "0.4.305",
19
19
  description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
20
20
  license: "MIT",
21
21
  type: "module",
@@ -15826,165 +15826,6 @@ var init_runFlow = __esm({
15826
15826
  }
15827
15827
  });
15828
15828
 
15829
- // src/scripts/previewBuildHelpers.ts
15830
- import { createDecipheriv, createHash as createHash3 } from "crypto";
15831
- function shortHash(s) {
15832
- return createHash3("sha256").update(s).digest("hex").slice(0, 6);
15833
- }
15834
- function previewAppName(repo, pr) {
15835
- const [owner, name] = repo.split("/");
15836
- if (!owner || !name) {
15837
- throw new Error(`invalid repo "${repo}", expected "owner/name"`);
15838
- }
15839
- return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
15840
- }
15841
- function basePreviewAppName(repo) {
15842
- const [owner, name] = repo.split("/");
15843
- if (!owner || !name) {
15844
- throw new Error(`invalid repo "${repo}", expected "owner/name"`);
15845
- }
15846
- return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
15847
- }
15848
- function decryptVaultPayload(payload, keyRaw) {
15849
- const parts = payload.split(":");
15850
- if (parts.length !== 4 || parts[0] !== "v1") {
15851
- throw new Error("invalid vault payload format");
15852
- }
15853
- const [, ivB64, ctB64, tagB64] = parts;
15854
- const key = /^[0-9a-fA-F]{64}$/.test(keyRaw) ? Buffer.from(keyRaw, "hex") : Buffer.from(keyRaw, "base64");
15855
- if (key.length !== 32) {
15856
- throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
15857
- }
15858
- const iv = Buffer.from(ivB64, "base64");
15859
- const ct = Buffer.from(ctB64, "base64");
15860
- const tag = Buffer.from(tagB64, "base64");
15861
- const decipher = createDecipheriv("aes-256-gcm", key, iv);
15862
- decipher.setAuthTag(tag);
15863
- return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
15864
- }
15865
- function buildEnvFromVault(doc) {
15866
- const buildEnv = {};
15867
- for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
15868
- if (!entry?.value) continue;
15869
- if (NEVER_PASS_TO_BUILD.has(name)) continue;
15870
- buildEnv[name] = entry.value;
15871
- }
15872
- const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
15873
- const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
15874
- return { buildEnv, buildMode };
15875
- }
15876
- function formatPreviewComment(args) {
15877
- const url = `https://${args.appName}.fly.dev`;
15878
- return [
15879
- "<!-- kody-fly-preview -->",
15880
- `\u2705 **Preview ready:** ${url}`,
15881
- "",
15882
- `<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
15883
- ].join("\n");
15884
- }
15885
- function defaultImageTag(repo, ref) {
15886
- return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
15887
- }
15888
- var NEVER_PASS_TO_BUILD;
15889
- var init_previewBuildHelpers = __esm({
15890
- "src/scripts/previewBuildHelpers.ts"() {
15891
- "use strict";
15892
- NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
15893
- "FLY_API_TOKEN",
15894
- "FLY_ORG_SLUG",
15895
- "FLY_DEFAULT_REGION",
15896
- "KODY_MASTER_KEY",
15897
- // Preview-config knob; consumed by the dispatcher before spawn.
15898
- "KODY_PREVIEW_BUILD_MODE"
15899
- ]);
15900
- }
15901
- });
15902
-
15903
- // src/scripts/previewBuildRun.ts
15904
- import { spawn as spawn4 } from "child_process";
15905
- async function runCmd(cmd, args, opts = {}) {
15906
- await new Promise((resolve10, reject) => {
15907
- const child = spawn4(cmd, args, {
15908
- cwd: opts.cwd,
15909
- env: { ...process.env, ...opts.env ?? {} },
15910
- stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
15911
- });
15912
- if (opts.input && child.stdin) {
15913
- child.stdin.write(opts.input);
15914
- child.stdin.end();
15915
- }
15916
- child.on("error", reject);
15917
- child.on("close", (code) => {
15918
- if (code === 0) resolve10();
15919
- else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
15920
- });
15921
- });
15922
- }
15923
- var init_previewBuildRun = __esm({
15924
- "src/scripts/previewBuildRun.ts"() {
15925
- "use strict";
15926
- }
15927
- });
15928
-
15929
- // src/scripts/previewBuildNamespace.ts
15930
- async function fetchGithubOidcToken(audience) {
15931
- const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
15932
- const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
15933
- if (!url || !requestToken) return null;
15934
- const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
15935
- headers: { Authorization: `Bearer ${requestToken}` },
15936
- signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
15937
- });
15938
- if (!res.ok) {
15939
- throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
15940
- }
15941
- const data = await res.json();
15942
- if (!data.value) throw new Error("OIDC token response missing `value`");
15943
- return data.value;
15944
- }
15945
- async function setupNamespaceBuilder(opts) {
15946
- try {
15947
- await runCmd("bash", ["-c", NSC_INSTALL]);
15948
- const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
15949
- if (!jwt) {
15950
- console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
15951
- return null;
15952
- }
15953
- await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
15954
- await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
15955
- console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
15956
- return opts.builderName;
15957
- } catch (err) {
15958
- console.warn(
15959
- "[preview-build] Namespace setup failed \u2014 falling back to local docker:",
15960
- err instanceof Error ? err.message : String(err)
15961
- );
15962
- return null;
15963
- }
15964
- }
15965
- var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS, NSC_INSTALL;
15966
- var init_previewBuildNamespace = __esm({
15967
- "src/scripts/previewBuildNamespace.ts"() {
15968
- "use strict";
15969
- init_previewBuildRun();
15970
- NSC_OIDC_AUDIENCE = "https://namespace.so";
15971
- REQ_TIMEOUT_MS = 15e3;
15972
- NSC_INSTALL = `
15973
- set -euo pipefail
15974
- if [ ! -x /usr/local/bin/nsc ]; then
15975
- ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
15976
- OS=$(uname -s | tr '[:upper:]' '[:lower:]')
15977
- curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
15978
- mkdir -p /tmp/nsc-extract
15979
- tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
15980
- NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
15981
- sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
15982
- fi
15983
- /usr/local/bin/nsc version
15984
- `;
15985
- }
15986
- });
15987
-
15988
15829
  // src/stateRepoGithub.ts
15989
15830
  import * as fs39 from "fs";
15990
15831
  import * as path37 from "path";
@@ -16004,7 +15845,7 @@ async function githubContentsFile(opts) {
16004
15845
  "X-GitHub-Api-Version": "2022-11-28",
16005
15846
  "User-Agent": "kody-engine"
16006
15847
  },
16007
- signal: AbortSignal.timeout(REQ_TIMEOUT_MS2)
15848
+ signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
16008
15849
  });
16009
15850
  if (res.status === 404) return null;
16010
15851
  if (!res.ok) {
@@ -16103,7 +15944,7 @@ async function writeGithubStateTextWithConfig(opts) {
16103
15944
  "User-Agent": "kody-engine"
16104
15945
  },
16105
15946
  body: JSON.stringify(payload),
16106
- signal: AbortSignal.timeout(REQ_TIMEOUT_MS2)
15947
+ signal: AbortSignal.timeout(REQ_TIMEOUT_MS)
16107
15948
  });
16108
15949
  if (!res.ok) {
16109
15950
  throw new Error(
@@ -16157,13 +15998,196 @@ async function persistJsonlFileToGithubState(opts) {
16157
15998
  }
16158
15999
  }
16159
16000
  }
16160
- var GITHUB_API, REQ_TIMEOUT_MS2;
16001
+ var GITHUB_API, REQ_TIMEOUT_MS;
16161
16002
  var init_stateRepoGithub = __esm({
16162
16003
  "src/stateRepoGithub.ts"() {
16163
16004
  "use strict";
16164
16005
  init_stateRepo();
16165
16006
  GITHUB_API = "https://api.github.com";
16166
- REQ_TIMEOUT_MS2 = 3e4;
16007
+ REQ_TIMEOUT_MS = 3e4;
16008
+ }
16009
+ });
16010
+
16011
+ // src/scripts/previewBuildHelpers.ts
16012
+ import { createDecipheriv, createHash as createHash3, hkdfSync } from "crypto";
16013
+ function shortHash(s) {
16014
+ return createHash3("sha256").update(s).digest("hex").slice(0, 6);
16015
+ }
16016
+ function previewAppName(repo, pr) {
16017
+ const [owner, name] = repo.split("/");
16018
+ if (!owner || !name) {
16019
+ throw new Error(`invalid repo "${repo}", expected "owner/name"`);
16020
+ }
16021
+ return `kp-${shortHash(owner)}-${shortHash(name)}-pr-${pr}`;
16022
+ }
16023
+ function basePreviewAppName(repo) {
16024
+ const [owner, name] = repo.split("/");
16025
+ if (!owner || !name) {
16026
+ throw new Error(`invalid repo "${repo}", expected "owner/name"`);
16027
+ }
16028
+ return `kp-${shortHash(owner)}-${shortHash(name)}-base`;
16029
+ }
16030
+ function decryptVaultPayload(payload, keyRaw) {
16031
+ const parts = payload.split(":");
16032
+ if (parts.length !== 4 || parts[0] !== "v1") {
16033
+ throw new Error("invalid vault payload format");
16034
+ }
16035
+ const [, ivB64, ctB64, tagB64] = parts;
16036
+ const key = decodeMasterKey(keyRaw);
16037
+ if (key.length !== 32) {
16038
+ throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
16039
+ }
16040
+ const iv = Buffer.from(ivB64, "base64");
16041
+ const ct = Buffer.from(ctB64, "base64");
16042
+ const tag = Buffer.from(tagB64, "base64");
16043
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
16044
+ decipher.setAuthTag(tag);
16045
+ return Buffer.concat([decipher.update(ct), decipher.final()]).toString("utf8");
16046
+ }
16047
+ function decodeMasterKey(keyRaw) {
16048
+ if (/^[0-9a-fA-F]{64}$/.test(keyRaw)) return Buffer.from(keyRaw, "hex");
16049
+ return Buffer.from(keyRaw.replace(/-/g, "+").replace(/_/g, "/"), "base64");
16050
+ }
16051
+ function derivePreviewVerifyKey(masterKeyRaw) {
16052
+ const masterKey = decodeMasterKey(masterKeyRaw);
16053
+ if (masterKey.length !== 32) {
16054
+ throw new Error("KODY_MASTER_KEY must decode to 32 bytes");
16055
+ }
16056
+ return Buffer.from(hkdfSync("sha256", masterKey, Buffer.alloc(0), PREVIEW_KEY_INFO, 32)).toString("hex");
16057
+ }
16058
+ function previewRuntimeEnv(args) {
16059
+ return {
16060
+ ...args.buildEnv,
16061
+ KODY_PREVIEW_VERIFY_KEY: derivePreviewVerifyKey(args.masterKey),
16062
+ KODY_REPO_CONTEXT: args.repo,
16063
+ KODY_PR: String(args.pr)
16064
+ };
16065
+ }
16066
+ function buildEnvFromVault(doc) {
16067
+ const buildEnv = {};
16068
+ for (const [name, entry] of Object.entries(doc.secrets ?? {})) {
16069
+ if (!entry?.value) continue;
16070
+ if (NEVER_PASS_TO_BUILD.has(name)) continue;
16071
+ buildEnv[name] = entry.value;
16072
+ }
16073
+ const raw = doc.secrets?.KODY_PREVIEW_BUILD_MODE?.value;
16074
+ const buildMode = raw?.toLowerCase().trim() === "dev" ? "dev" : "prod";
16075
+ return { buildEnv, buildMode };
16076
+ }
16077
+ function formatPreviewComment(args) {
16078
+ const url = `https://${args.appName}.fly.dev`;
16079
+ return [
16080
+ "<!-- kody-fly-preview -->",
16081
+ `\u2705 **Preview ready:** ${url}`,
16082
+ "",
16083
+ `<sub>App: \`${args.appName}\` \xB7 Commit: \`${args.ref.slice(0, 7)}\` \xB7 Updated: ${args.nowIso}</sub>`
16084
+ ].join("\n");
16085
+ }
16086
+ function defaultImageTag(repo, ref) {
16087
+ return createHash3("sha256").update(`${repo}@${ref}`).digest("hex").slice(0, 12);
16088
+ }
16089
+ var NEVER_PASS_TO_BUILD, PREVIEW_KEY_INFO;
16090
+ var init_previewBuildHelpers = __esm({
16091
+ "src/scripts/previewBuildHelpers.ts"() {
16092
+ "use strict";
16093
+ NEVER_PASS_TO_BUILD = /* @__PURE__ */ new Set([
16094
+ "FLY_API_TOKEN",
16095
+ "FLY_ORG_SLUG",
16096
+ "FLY_DEFAULT_REGION",
16097
+ "KODY_MASTER_KEY",
16098
+ // Preview-config knob; consumed by the dispatcher before spawn.
16099
+ "KODY_PREVIEW_BUILD_MODE",
16100
+ "KODY_PREVIEW_VERIFY_KEY",
16101
+ "KODY_REPO_CONTEXT",
16102
+ "KODY_PR",
16103
+ "KODY_BRANCH"
16104
+ ]);
16105
+ PREVIEW_KEY_INFO = "kody-preview:v1";
16106
+ }
16107
+ });
16108
+
16109
+ // src/scripts/previewBuildRun.ts
16110
+ import { spawn as spawn4 } from "child_process";
16111
+ async function runCmd(cmd, args, opts = {}) {
16112
+ await new Promise((resolve10, reject) => {
16113
+ const child = spawn4(cmd, args, {
16114
+ cwd: opts.cwd,
16115
+ env: { ...process.env, ...opts.env ?? {} },
16116
+ stdio: opts.input ? ["pipe", "inherit", "inherit"] : "inherit"
16117
+ });
16118
+ if (opts.input && child.stdin) {
16119
+ child.stdin.write(opts.input);
16120
+ child.stdin.end();
16121
+ }
16122
+ child.on("error", reject);
16123
+ child.on("close", (code) => {
16124
+ if (code === 0) resolve10();
16125
+ else reject(new Error(`${cmd} ${args.join(" ")} exited ${code}`));
16126
+ });
16127
+ });
16128
+ }
16129
+ var init_previewBuildRun = __esm({
16130
+ "src/scripts/previewBuildRun.ts"() {
16131
+ "use strict";
16132
+ }
16133
+ });
16134
+
16135
+ // src/scripts/previewBuildNamespace.ts
16136
+ async function fetchGithubOidcToken(audience) {
16137
+ const url = process.env.ACTIONS_ID_TOKEN_REQUEST_URL?.trim();
16138
+ const requestToken = process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN?.trim();
16139
+ if (!url || !requestToken) return null;
16140
+ const res = await fetch(`${url}&audience=${encodeURIComponent(audience)}`, {
16141
+ headers: { Authorization: `Bearer ${requestToken}` },
16142
+ signal: AbortSignal.timeout(REQ_TIMEOUT_MS2)
16143
+ });
16144
+ if (!res.ok) {
16145
+ throw new Error(`OIDC token request failed: ${res.status} ${res.statusText}`);
16146
+ }
16147
+ const data = await res.json();
16148
+ if (!data.value) throw new Error("OIDC token response missing `value`");
16149
+ return data.value;
16150
+ }
16151
+ async function setupNamespaceBuilder(opts) {
16152
+ try {
16153
+ await runCmd("bash", ["-c", NSC_INSTALL]);
16154
+ const jwt = await fetchGithubOidcToken(NSC_OIDC_AUDIENCE);
16155
+ if (!jwt) {
16156
+ console.warn("[preview-build] no GitHub OIDC token (id-token: write missing?) \u2014 local docker build");
16157
+ return null;
16158
+ }
16159
+ await runCmd("nsc", ["auth", "exchange-oidc-token", "--tenant_id", opts.tenantId, "--token", jwt]);
16160
+ await runCmd("nsc", ["docker", "buildx", "setup", "--name", opts.builderName]);
16161
+ console.log(`[preview-build] Namespace remote builder ready (${opts.builderName})`);
16162
+ return opts.builderName;
16163
+ } catch (err) {
16164
+ console.warn(
16165
+ "[preview-build] Namespace setup failed \u2014 falling back to local docker:",
16166
+ err instanceof Error ? err.message : String(err)
16167
+ );
16168
+ return null;
16169
+ }
16170
+ }
16171
+ var NSC_OIDC_AUDIENCE, REQ_TIMEOUT_MS2, NSC_INSTALL;
16172
+ var init_previewBuildNamespace = __esm({
16173
+ "src/scripts/previewBuildNamespace.ts"() {
16174
+ "use strict";
16175
+ init_previewBuildRun();
16176
+ NSC_OIDC_AUDIENCE = "https://namespace.so";
16177
+ REQ_TIMEOUT_MS2 = 15e3;
16178
+ NSC_INSTALL = `
16179
+ set -euo pipefail
16180
+ if [ ! -x /usr/local/bin/nsc ]; then
16181
+ ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
16182
+ OS=$(uname -s | tr '[:upper:]' '[:lower:]')
16183
+ curl -fsSL "https://get.namespace.so/packages/nsc/latest?arch=\${ARCH}&os=\${OS}" -o /tmp/nsc.tar.gz
16184
+ mkdir -p /tmp/nsc-extract
16185
+ tar -xzf /tmp/nsc.tar.gz -C /tmp/nsc-extract
16186
+ NSC_BIN=$(find /tmp/nsc-extract -type f -name nsc | head -1)
16187
+ sudo install -m 0755 "$NSC_BIN" /usr/local/bin/nsc
16188
+ fi
16189
+ /usr/local/bin/nsc version
16190
+ `;
16167
16191
  }
16168
16192
  });
16169
16193
 
@@ -16375,10 +16399,10 @@ var FLY_MACHINES, FLY_GRAPHQL, REQ_TIMEOUT_MS3, runPreviewBuild;
16375
16399
  var init_runPreviewBuild = __esm({
16376
16400
  "src/scripts/runPreviewBuild.ts"() {
16377
16401
  "use strict";
16402
+ init_stateRepoGithub();
16378
16403
  init_previewBuildHelpers();
16379
16404
  init_previewBuildNamespace();
16380
16405
  init_previewBuildRun();
16381
- init_stateRepoGithub();
16382
16406
  FLY_MACHINES = "https://api.machines.dev/v1";
16383
16407
  FLY_GRAPHQL = "https://api.fly.io/graphql";
16384
16408
  REQ_TIMEOUT_MS3 = 3e4;
@@ -16503,7 +16527,7 @@ var init_runPreviewBuild = __esm({
16503
16527
  appName,
16504
16528
  region,
16505
16529
  image: `registry.fly.io/${appName}:${tag}`,
16506
- env: buildEnv
16530
+ env: previewRuntimeEnv({ buildEnv, masterKey, pr, repo })
16507
16531
  },
16508
16532
  flyToken
16509
16533
  );
@@ -23060,7 +23084,7 @@ async function runCapabilityFallbackTick(deps) {
23060
23084
  }
23061
23085
 
23062
23086
  // src/pool/keys.ts
23063
- import { hkdfSync } from "crypto";
23087
+ import { hkdfSync as hkdfSync2 } from "crypto";
23064
23088
  var POOL_API_KEY_INFO = "kody-pool-api:v1";
23065
23089
  var RUNNER_API_KEY_INFO = "kody-runner-api:v1";
23066
23090
  function masterKeyBytes(raw) {
@@ -23072,7 +23096,7 @@ function masterKeyBytes(raw) {
23072
23096
  return Buffer.from(v.replace(/-/g, "+").replace(/_/g, "/"), "base64");
23073
23097
  }
23074
23098
  function deriveKey(master, info, length = 32) {
23075
- return Buffer.from(hkdfSync("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
23099
+ return Buffer.from(hkdfSync2("sha256", master, Buffer.alloc(0), info, length)).toString("hex");
23076
23100
  }
23077
23101
  function derivePoolApiKey(master) {
23078
23102
  return deriveKey(master, POOL_API_KEY_INFO);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.4.304",
3
+ "version": "0.4.305",
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",