@kody-ade/kody-engine 0.4.600 → 0.4.602
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 +86 -18
- 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.
|
|
18
|
+
version: "0.4.602",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -16521,7 +16521,7 @@ function composeAuthBlock(authProfile, login, password) {
|
|
|
16521
16521
|
return `Auth: a saved Playwright \`storageState.json\` is available at \`${authProfile}\`. Pass it to the browser via the \`storageState\` parameter so the session starts pre-authenticated.`;
|
|
16522
16522
|
}
|
|
16523
16523
|
if (login && password) {
|
|
16524
|
-
return `Auth:
|
|
16524
|
+
return `Auth: QA credentials for \`${login}\` are configured. The engine will prepare the authenticated browser session before the agent starts; the password is never included in agent context.`;
|
|
16525
16525
|
}
|
|
16526
16526
|
if (login) {
|
|
16527
16527
|
return `Auth: username \`${login}\` is configured but no \`LOGIN_PASSWORD\` secret was found. Note auth-gated surfaces as gaps.`;
|
|
@@ -18385,15 +18385,15 @@ function writeKodyStorageState(input) {
|
|
|
18385
18385
|
repo: input.repo,
|
|
18386
18386
|
token: input.token,
|
|
18387
18387
|
addedAt: now,
|
|
18388
|
-
isLogin: true
|
|
18389
|
-
user: input.user
|
|
18388
|
+
isLogin: true
|
|
18390
18389
|
};
|
|
18390
|
+
const unresolvedUser = { login: "", avatar_url: "", id: 0 };
|
|
18391
18391
|
const auth = {
|
|
18392
18392
|
repoUrl: input.repoUrl,
|
|
18393
18393
|
owner: input.owner,
|
|
18394
18394
|
repo: input.repo,
|
|
18395
18395
|
token: input.token,
|
|
18396
|
-
user:
|
|
18396
|
+
user: unresolvedUser,
|
|
18397
18397
|
loggedInAt: now,
|
|
18398
18398
|
repos: [repoEntry],
|
|
18399
18399
|
currentRepoIndex: 0
|
|
@@ -18410,6 +18410,46 @@ function writeKodyStorageState(input) {
|
|
|
18410
18410
|
fs48.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
|
|
18411
18411
|
return { directory, file };
|
|
18412
18412
|
}
|
|
18413
|
+
function parseSetCookie(value, hostname) {
|
|
18414
|
+
const parts = value.split(";").map((part) => part.trim());
|
|
18415
|
+
const pair = parts.shift() ?? "";
|
|
18416
|
+
const separator = pair.indexOf("=");
|
|
18417
|
+
if (separator <= 0) throw new Error("login response returned an invalid session cookie");
|
|
18418
|
+
const attributes = /* @__PURE__ */ new Map();
|
|
18419
|
+
for (const part of parts) {
|
|
18420
|
+
const index = part.indexOf("=");
|
|
18421
|
+
attributes.set(
|
|
18422
|
+
(index < 0 ? part : part.slice(0, index)).toLowerCase(),
|
|
18423
|
+
index < 0 ? "" : part.slice(index + 1)
|
|
18424
|
+
);
|
|
18425
|
+
}
|
|
18426
|
+
const sameSite = attributes.get("samesite")?.toLowerCase();
|
|
18427
|
+
return {
|
|
18428
|
+
name: pair.slice(0, separator),
|
|
18429
|
+
value: pair.slice(separator + 1),
|
|
18430
|
+
domain: attributes.get("domain")?.replace(/^\./, "") || hostname,
|
|
18431
|
+
path: attributes.get("path") || "/",
|
|
18432
|
+
expires: -1,
|
|
18433
|
+
httpOnly: attributes.has("httponly"),
|
|
18434
|
+
secure: attributes.has("secure"),
|
|
18435
|
+
sameSite: sameSite === "strict" ? "Strict" : sameSite === "none" ? "None" : "Lax"
|
|
18436
|
+
};
|
|
18437
|
+
}
|
|
18438
|
+
function writeCookieStorageState(targetUrl, setCookies) {
|
|
18439
|
+
const target = new URL(targetUrl);
|
|
18440
|
+
const directory = fs48.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
|
|
18441
|
+
fs48.chmodSync(directory, 448);
|
|
18442
|
+
const file = path45.join(directory, "storage-state.json");
|
|
18443
|
+
fs48.writeFileSync(
|
|
18444
|
+
file,
|
|
18445
|
+
JSON.stringify({
|
|
18446
|
+
cookies: setCookies.map((cookie) => parseSetCookie(cookie, target.hostname)),
|
|
18447
|
+
origins: []
|
|
18448
|
+
}),
|
|
18449
|
+
{ mode: 384 }
|
|
18450
|
+
);
|
|
18451
|
+
return { directory, file };
|
|
18452
|
+
}
|
|
18413
18453
|
function configurePlaywright(profile, storageStatePath) {
|
|
18414
18454
|
const playwright = profile.claudeCode.mcpServers.find((server) => server.name === "playwright");
|
|
18415
18455
|
if (!playwright) throw new Error("Playwright MCP server is not configured");
|
|
@@ -18478,25 +18518,19 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
|
|
|
18478
18518
|
let state;
|
|
18479
18519
|
try {
|
|
18480
18520
|
const requested = githubRepositoryParts(repositoryUrl);
|
|
18481
|
-
const
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
"repository"
|
|
18487
|
-
)
|
|
18488
|
-
]);
|
|
18521
|
+
const repository = await githubJson(
|
|
18522
|
+
`https://api.github.com/repos/${encodeURIComponent(requested.owner)}/${encodeURIComponent(requested.repo)}`,
|
|
18523
|
+
credential.value,
|
|
18524
|
+
"repository"
|
|
18525
|
+
);
|
|
18489
18526
|
const [owner, repo] = repository.full_name.split("/");
|
|
18490
|
-
if (!owner || !repo
|
|
18491
|
-
throw new Error("GitHub returned incomplete identity data");
|
|
18492
|
-
}
|
|
18527
|
+
if (!owner || !repo) throw new Error("GitHub returned incomplete repository data");
|
|
18493
18528
|
state = writeKodyStorageState({
|
|
18494
18529
|
origin: browserOrigin(input.targetUrl),
|
|
18495
18530
|
repoUrl: `https://github.com/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}`,
|
|
18496
18531
|
owner,
|
|
18497
18532
|
repo,
|
|
18498
|
-
token: credential.value
|
|
18499
|
-
user
|
|
18533
|
+
token: credential.value
|
|
18500
18534
|
});
|
|
18501
18535
|
configurePlaywright(profile, state.file);
|
|
18502
18536
|
const authDirectory = state.directory;
|
|
@@ -18518,6 +18552,34 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
|
|
|
18518
18552
|
return false;
|
|
18519
18553
|
}
|
|
18520
18554
|
}
|
|
18555
|
+
async function prepareEmailPasswordBrowserAuth(ctx, profile, input) {
|
|
18556
|
+
const password = await resolveRuntimeSecret("LOGIN_PASSWORD", ctx);
|
|
18557
|
+
if (!input.login || !password.value) return false;
|
|
18558
|
+
let state;
|
|
18559
|
+
try {
|
|
18560
|
+
const origin = browserOrigin(input.targetUrl);
|
|
18561
|
+
const response = await fetch(`${origin}/api/auth/sign-in/email`, {
|
|
18562
|
+
method: "POST",
|
|
18563
|
+
headers: { "content-type": "application/json", origin },
|
|
18564
|
+
body: JSON.stringify({ email: input.login, password: password.value })
|
|
18565
|
+
});
|
|
18566
|
+
if (!response.ok) throw new Error(`app login returned ${response.status}`);
|
|
18567
|
+
const headers = response.headers;
|
|
18568
|
+
const cookies = headers.getSetCookie?.() ?? (headers.get("set-cookie") ? [headers.get("set-cookie")] : []);
|
|
18569
|
+
if (cookies.length === 0) throw new Error("app login returned no session cookie");
|
|
18570
|
+
state = writeCookieStorageState(input.targetUrl, cookies);
|
|
18571
|
+
configurePlaywright(profile, state.file);
|
|
18572
|
+
const authDirectory = state.directory;
|
|
18573
|
+
registerRuntimeCleanup(ctx, () => fs48.rmSync(authDirectory, { recursive: true, force: true }));
|
|
18574
|
+
ctx.data.qaAuthBlock = "Auth: the app is already signed in through an engine-provided browser session. The login credentials are not available to you; never request, reveal, or report them.";
|
|
18575
|
+
return true;
|
|
18576
|
+
} catch (error) {
|
|
18577
|
+
if (state) fs48.rmSync(state.directory, { recursive: true, force: true });
|
|
18578
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
18579
|
+
ctx.data.qaAuthBlock = `Auth: the engine could not prepare the app login (${reason}). Note this authenticated surface as a gap.`;
|
|
18580
|
+
return false;
|
|
18581
|
+
}
|
|
18582
|
+
}
|
|
18521
18583
|
var prepareBrowserAuth;
|
|
18522
18584
|
var init_prepareBrowserAuth = __esm({
|
|
18523
18585
|
"src/scripts/prepareBrowserAuth.ts"() {
|
|
@@ -18744,6 +18806,12 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
18744
18806
|
configureBrowser(ctx, profile, requirements);
|
|
18745
18807
|
if (requirements.qaCredentials) {
|
|
18746
18808
|
await loadQaContext(ctx, profile);
|
|
18809
|
+
const capabilityInput = ctx.data.capabilityInput && typeof ctx.data.capabilityInput === "object" && !Array.isArray(ctx.data.capabilityInput) ? ctx.data.capabilityInput : {};
|
|
18810
|
+
const targetUrl = typeof capabilityInput.url === "string" ? capabilityInput.url : typeof capabilityInput.targetUrl === "string" ? capabilityInput.targetUrl : "";
|
|
18811
|
+
await prepareEmailPasswordBrowserAuth(ctx, profile, {
|
|
18812
|
+
login: String(ctx.data.qaLogin ?? ""),
|
|
18813
|
+
targetUrl
|
|
18814
|
+
});
|
|
18747
18815
|
}
|
|
18748
18816
|
if (requirements.githubTestToken) {
|
|
18749
18817
|
const capabilityInput = ctx.data.capabilityInput && typeof ctx.data.capabilityInput === "object" && !Array.isArray(ctx.data.capabilityInput) ? ctx.data.capabilityInput : {};
|
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.602",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative implementation profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|