@kody-ade/kody-engine 0.4.241 → 0.4.243
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/agent-actions/agent-factory/profile.json +47 -0
- package/dist/agent-actions/agent-factory/prompt.md +62 -0
- package/dist/agent-responsibilities/agent-factory/agent-responsibility.md +10 -0
- package/dist/agent-responsibilities/agent-factory/profile.json +7 -0
- package/dist/bin/kody.js +255 -18
- package/kody.config.schema.json +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-factory",
|
|
3
|
+
"action": "agent-factory",
|
|
4
|
+
"describe": "Create or assemble Kody agency model definitions from an operator request.",
|
|
5
|
+
"capabilityKind": "act",
|
|
6
|
+
"role": "primitive",
|
|
7
|
+
"kind": "oneshot",
|
|
8
|
+
"inputs": [
|
|
9
|
+
{
|
|
10
|
+
"name": "issue",
|
|
11
|
+
"flag": "--issue",
|
|
12
|
+
"type": "int",
|
|
13
|
+
"required": true,
|
|
14
|
+
"describe": "GitHub issue number containing the operator request."
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"claudeCode": {
|
|
18
|
+
"model": "inherit",
|
|
19
|
+
"permissionMode": "default",
|
|
20
|
+
"maxTurns": null,
|
|
21
|
+
"maxTurnTimeoutSec": 1200,
|
|
22
|
+
"systemPromptAppend": null,
|
|
23
|
+
"cacheable": true,
|
|
24
|
+
"enableVerifyTool": false,
|
|
25
|
+
"tools": ["Read", "Grep", "Glob"],
|
|
26
|
+
"hooks": [],
|
|
27
|
+
"skills": [],
|
|
28
|
+
"commands": [],
|
|
29
|
+
"subagents": [],
|
|
30
|
+
"plugins": [],
|
|
31
|
+
"mcpServers": []
|
|
32
|
+
},
|
|
33
|
+
"cliTools": [],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"preflight": [
|
|
36
|
+
{ "script": "loadIssueContext" },
|
|
37
|
+
{ "script": "composePrompt" }
|
|
38
|
+
],
|
|
39
|
+
"postflight": [
|
|
40
|
+
{ "script": "parseAgentResult" },
|
|
41
|
+
{ "script": "openAgentFactoryStatePr" }
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"output": {
|
|
45
|
+
"actionTypes": ["AGENT_FACTORY_COMPLETED", "AGENT_FACTORY_FAILED", "AGENT_NOT_RUN"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
You are Kody's agent factory. Convert the operator request into review-ready Kody agency model definitions.
|
|
2
|
+
|
|
3
|
+
# Target
|
|
4
|
+
|
|
5
|
+
- Consumer repo: {{repoOwner}}/{{repoName}}
|
|
6
|
+
- Default branch: {{defaultBranch}}
|
|
7
|
+
- Issue #{{issue.number}}: {{issue.title}}
|
|
8
|
+
|
|
9
|
+
{{agentResponsibilityReference}}
|
|
10
|
+
|
|
11
|
+
# Operator Request
|
|
12
|
+
|
|
13
|
+
{{issue.body}}
|
|
14
|
+
|
|
15
|
+
# Recent comments (most recent first, truncated)
|
|
16
|
+
|
|
17
|
+
{{issue.commentsFormatted}}
|
|
18
|
+
|
|
19
|
+
# Task
|
|
20
|
+
|
|
21
|
+
Design the smallest Kody model structure that satisfies the request. You may create or assemble simple agentActions, agentResponsibilities, loops, goals, and agents.
|
|
22
|
+
|
|
23
|
+
Use the current Kody vocabulary:
|
|
24
|
+
|
|
25
|
+
- agent: who runs
|
|
26
|
+
- agentResponsibility: why/when and public action ownership
|
|
27
|
+
- agentAction: how work runs
|
|
28
|
+
- goal: related task list/state
|
|
29
|
+
|
|
30
|
+
# Boundaries
|
|
31
|
+
|
|
32
|
+
- Do not edit files directly.
|
|
33
|
+
- Do not run `git`, `gh`, shell commands, or any external command.
|
|
34
|
+
- Do not activate generated definitions yourself.
|
|
35
|
+
- Do not create a consumer-repo PR.
|
|
36
|
+
- The deterministic postflight will open a review PR in the configured state repo under the configured state path.
|
|
37
|
+
- Put generated file paths relative to the consumer repo, usually under `.kody/...`.
|
|
38
|
+
- Produce complete file contents. Do not describe patches.
|
|
39
|
+
- Prefer a small bundle over a broad framework. Include assumptions in the summary.
|
|
40
|
+
|
|
41
|
+
# Final Output Contract
|
|
42
|
+
|
|
43
|
+
If the request is too ambiguous to produce review-ready definitions, output one line:
|
|
44
|
+
|
|
45
|
+
FAILED: <specific missing decision>
|
|
46
|
+
|
|
47
|
+
Otherwise output exactly:
|
|
48
|
+
|
|
49
|
+
DONE
|
|
50
|
+
PR_SUMMARY:
|
|
51
|
+
{
|
|
52
|
+
"title": "short title",
|
|
53
|
+
"summary": "human explanation and assumptions",
|
|
54
|
+
"files": [
|
|
55
|
+
{
|
|
56
|
+
"path": ".kody/agent-actions/example/profile.json",
|
|
57
|
+
"content": "{\n \"name\": \"example\"\n}\n"
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
The `PR_SUMMARY` value must be valid JSON. Do not wrap it in a markdown code fence.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Agent Factory
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Create or assemble Kody agency model definitions from an operator request.
|
|
6
|
+
|
|
7
|
+
## Instructions
|
|
8
|
+
|
|
9
|
+
Use the `agent-factory` agentAction for the implementation details.
|
|
10
|
+
The agentResponsibility owns the public action name and review boundary; the agentAction owns model reasoning and state-repo PR creation.
|
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.243",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative agentAction profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -334,9 +334,22 @@ function is404(err) {
|
|
|
334
334
|
}
|
|
335
335
|
function parseStateRepoSlug(slug, field = "stateRepo") {
|
|
336
336
|
const value = slug.trim();
|
|
337
|
-
|
|
337
|
+
let repoPath = value;
|
|
338
|
+
if (/^https?:\/\//i.test(value)) {
|
|
339
|
+
let parsed;
|
|
340
|
+
try {
|
|
341
|
+
parsed = new URL(value);
|
|
342
|
+
} catch {
|
|
343
|
+
throw new Error(`kody.config.json: ${field} must be a GitHub repository URL`);
|
|
344
|
+
}
|
|
345
|
+
if (parsed.protocol !== "https:" || parsed.hostname !== "github.com") {
|
|
346
|
+
throw new Error(`kody.config.json: ${field} must be a https://github.com repository URL`);
|
|
347
|
+
}
|
|
348
|
+
repoPath = parsed.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
|
|
349
|
+
}
|
|
350
|
+
const parts = repoPath.split("/");
|
|
338
351
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
339
|
-
throw new Error(`kody.config.json: ${field} must
|
|
352
|
+
throw new Error(`kody.config.json: ${field} must be a https://github.com/owner/repo URL`);
|
|
340
353
|
}
|
|
341
354
|
for (const part of parts) {
|
|
342
355
|
if (!/^[A-Za-z0-9_.-]+$/.test(part)) {
|
|
@@ -537,7 +550,7 @@ function parseStateConfig(raw, github) {
|
|
|
537
550
|
const nested = recordValue(raw.state) ?? {};
|
|
538
551
|
const repoRaw = typeof raw.stateRepo === "string" ? raw.stateRepo : nested.repo;
|
|
539
552
|
const pathRaw = typeof raw.statePath === "string" ? raw.statePath : nested.path;
|
|
540
|
-
const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() :
|
|
553
|
+
const stateRepo = typeof repoRaw === "string" && repoRaw.trim().length > 0 ? repoRaw.trim() : `https://github.com/${String(github.owner)}/kody-state`;
|
|
541
554
|
parseStateRepoSlug(stateRepo);
|
|
542
555
|
const statePath2 = typeof pathRaw === "string" && pathRaw.trim().length > 0 ? pathRaw.trim() : String(github.repo);
|
|
543
556
|
return {
|
|
@@ -2393,6 +2406,7 @@ function parseAgentResponsibilityConfig(raw) {
|
|
|
2393
2406
|
mentions: stringList(raw.mentions).map((m) => m.replace(/^@/, "")),
|
|
2394
2407
|
tools,
|
|
2395
2408
|
agentActions: stringList(raw.agentActions),
|
|
2409
|
+
capabilityKind: capabilityKindField(raw.capabilityKind),
|
|
2396
2410
|
describe: stringField(raw.describe),
|
|
2397
2411
|
stage: stringField(raw.stage),
|
|
2398
2412
|
readsFrom: stringList(raw.readsFrom ?? raw.reads_from),
|
|
@@ -2432,6 +2446,10 @@ function stringList(value) {
|
|
|
2432
2446
|
}
|
|
2433
2447
|
return [];
|
|
2434
2448
|
}
|
|
2449
|
+
function capabilityKindField(value) {
|
|
2450
|
+
if (value === "observe" || value === "act" || value === "verify") return value;
|
|
2451
|
+
return void 0;
|
|
2452
|
+
}
|
|
2435
2453
|
var AGENT_RESPONSIBILITY_PROFILE_FILE, AGENT_RESPONSIBILITY_BODY_FILE;
|
|
2436
2454
|
var init_agent_responsibilityFolders = __esm({
|
|
2437
2455
|
"src/agent-responsibilityFolders.ts"() {
|
|
@@ -2737,6 +2755,7 @@ function listFolderAgentResponsibilityActions(root, source) {
|
|
|
2737
2755
|
cliArgs,
|
|
2738
2756
|
source,
|
|
2739
2757
|
describe: agentResponsibility.config.describe ?? agentResponsibility.title,
|
|
2758
|
+
capabilityKind: agentResponsibility.config.capabilityKind,
|
|
2740
2759
|
profilePath: agentResponsibility.profilePath,
|
|
2741
2760
|
bodyPath: agentResponsibility.bodyPath
|
|
2742
2761
|
});
|
|
@@ -2759,6 +2778,7 @@ function listBuiltinAgentResponsibilityActions(root = getBuiltinAgentResponsibil
|
|
|
2759
2778
|
cliArgs: {},
|
|
2760
2779
|
source: "builtin",
|
|
2761
2780
|
describe: agentResponsibility.config.describe ?? agentResponsibility.title,
|
|
2781
|
+
capabilityKind: agentResponsibility.config.capabilityKind,
|
|
2762
2782
|
profilePath: agentResponsibility.profilePath,
|
|
2763
2783
|
bodyPath: agentResponsibility.bodyPath
|
|
2764
2784
|
});
|
|
@@ -11252,6 +11272,220 @@ var init_notifyTerminal = __esm({
|
|
|
11252
11272
|
}
|
|
11253
11273
|
});
|
|
11254
11274
|
|
|
11275
|
+
// src/scripts/openAgentFactoryStatePr.ts
|
|
11276
|
+
function parseAgentFactoryBundle(raw) {
|
|
11277
|
+
const jsonText = stripJsonFence(raw);
|
|
11278
|
+
let parsed;
|
|
11279
|
+
try {
|
|
11280
|
+
parsed = JSON.parse(jsonText);
|
|
11281
|
+
} catch (err) {
|
|
11282
|
+
throw new Error(`openAgentFactoryStatePr: PR_SUMMARY must be valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
11283
|
+
}
|
|
11284
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
11285
|
+
throw new Error("openAgentFactoryStatePr: PR_SUMMARY must be a JSON object");
|
|
11286
|
+
}
|
|
11287
|
+
const value = parsed;
|
|
11288
|
+
const title = readRequiredJsonString(value.title, "title");
|
|
11289
|
+
const summary = readRequiredJsonString(value.summary, "summary");
|
|
11290
|
+
if (!Array.isArray(value.files) || value.files.length === 0) {
|
|
11291
|
+
throw new Error("openAgentFactoryStatePr: files must be a non-empty array");
|
|
11292
|
+
}
|
|
11293
|
+
const files = value.files.map((item, index) => {
|
|
11294
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
11295
|
+
throw new Error(`openAgentFactoryStatePr: files[${index}] must be an object`);
|
|
11296
|
+
}
|
|
11297
|
+
const file = item;
|
|
11298
|
+
return {
|
|
11299
|
+
path: readRequiredJsonString(file.path, `files[${index}].path`),
|
|
11300
|
+
content: readJsonString(file.content, `files[${index}].content`)
|
|
11301
|
+
};
|
|
11302
|
+
});
|
|
11303
|
+
return { title, summary, files };
|
|
11304
|
+
}
|
|
11305
|
+
function buildAgentFactoryBranchName(issueNumber, title, now = Date.now()) {
|
|
11306
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48).replace(/-+$/g, "");
|
|
11307
|
+
const suffix = slug ? `-${slug}` : "";
|
|
11308
|
+
return `agent-factory/issue-${issueNumber}-${now.toString(36)}${suffix}`;
|
|
11309
|
+
}
|
|
11310
|
+
function normalizeBundleFiles(ctx, bundle) {
|
|
11311
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11312
|
+
return bundle.files.map((file, index) => {
|
|
11313
|
+
if (file.path.startsWith("/") || file.path.includes("\\")) {
|
|
11314
|
+
throw new Error(`openAgentFactoryStatePr: files[${index}].path must be a relative POSIX path`);
|
|
11315
|
+
}
|
|
11316
|
+
const relativePath = normalizeStatePath(file.path, `files[${index}].path`);
|
|
11317
|
+
if (seen.has(relativePath)) {
|
|
11318
|
+
throw new Error(`openAgentFactoryStatePr: duplicate generated file path: ${relativePath}`);
|
|
11319
|
+
}
|
|
11320
|
+
seen.add(relativePath);
|
|
11321
|
+
return {
|
|
11322
|
+
...file,
|
|
11323
|
+
path: relativePath,
|
|
11324
|
+
targetPath: stateRepoPath(ctx.config, relativePath)
|
|
11325
|
+
};
|
|
11326
|
+
});
|
|
11327
|
+
}
|
|
11328
|
+
function stripJsonFence(raw) {
|
|
11329
|
+
const text = raw.trim();
|
|
11330
|
+
const fence = text.match(/^```(?:json)?\s*\n([\s\S]*?)\n```$/i);
|
|
11331
|
+
return (fence ? fence[1] : text).trim();
|
|
11332
|
+
}
|
|
11333
|
+
function readIssueNumber(ctx) {
|
|
11334
|
+
const issueNumber = ctx.args.issue;
|
|
11335
|
+
if (typeof issueNumber !== "number" || !Number.isInteger(issueNumber) || issueNumber <= 0) {
|
|
11336
|
+
throw new Error("openAgentFactoryStatePr: ctx.args.issue must be a positive integer");
|
|
11337
|
+
}
|
|
11338
|
+
return issueNumber;
|
|
11339
|
+
}
|
|
11340
|
+
function readRequiredJsonString(value, field) {
|
|
11341
|
+
const text = readJsonString(value, field).trim();
|
|
11342
|
+
if (!text) throw new Error(`openAgentFactoryStatePr: ${field} must be a non-empty string`);
|
|
11343
|
+
return text;
|
|
11344
|
+
}
|
|
11345
|
+
function readJsonString(value, field) {
|
|
11346
|
+
if (typeof value !== "string") throw new Error(`openAgentFactoryStatePr: ${field} must be a string`);
|
|
11347
|
+
return value;
|
|
11348
|
+
}
|
|
11349
|
+
function requireString2(value, label) {
|
|
11350
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
11351
|
+
throw new Error(`openAgentFactoryStatePr: missing ${label}`);
|
|
11352
|
+
}
|
|
11353
|
+
return value;
|
|
11354
|
+
}
|
|
11355
|
+
function ghJson(args, cwd, input) {
|
|
11356
|
+
const raw = gh(args, input === void 0 ? { cwd } : { cwd, input: JSON.stringify(input) });
|
|
11357
|
+
if (!raw) return {};
|
|
11358
|
+
try {
|
|
11359
|
+
return JSON.parse(raw);
|
|
11360
|
+
} catch (err) {
|
|
11361
|
+
throw new Error(`openAgentFactoryStatePr: gh api returned invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
11362
|
+
}
|
|
11363
|
+
}
|
|
11364
|
+
function renderPullRequestBody(ctx, bundle, files) {
|
|
11365
|
+
const issueNumber = readIssueNumber(ctx);
|
|
11366
|
+
return [
|
|
11367
|
+
"Agent factory generated a Kody agency model bundle for review.",
|
|
11368
|
+
"",
|
|
11369
|
+
`Source issue: ${ctx.config.github.owner}/${ctx.config.github.repo}#${issueNumber}`,
|
|
11370
|
+
"",
|
|
11371
|
+
"## Summary",
|
|
11372
|
+
"",
|
|
11373
|
+
bundle.summary,
|
|
11374
|
+
"",
|
|
11375
|
+
"## Files",
|
|
11376
|
+
"",
|
|
11377
|
+
...files.map((file) => `- \`${file.targetPath}\``),
|
|
11378
|
+
"",
|
|
11379
|
+
"Generated definitions are inactive until this state-repo PR is reviewed and merged."
|
|
11380
|
+
].join("\n");
|
|
11381
|
+
}
|
|
11382
|
+
function renderIssueComment(owner, repo, prUrl, bundle) {
|
|
11383
|
+
return [
|
|
11384
|
+
`agent-factory opened a state-repo review PR: ${prUrl}`,
|
|
11385
|
+
"",
|
|
11386
|
+
`State repo: ${owner}/${repo}`,
|
|
11387
|
+
"",
|
|
11388
|
+
"Summary:",
|
|
11389
|
+
bundle.summary
|
|
11390
|
+
].join("\n");
|
|
11391
|
+
}
|
|
11392
|
+
var openAgentFactoryStatePr;
|
|
11393
|
+
var init_openAgentFactoryStatePr = __esm({
|
|
11394
|
+
"src/scripts/openAgentFactoryStatePr.ts"() {
|
|
11395
|
+
"use strict";
|
|
11396
|
+
init_issue();
|
|
11397
|
+
init_stateRepo();
|
|
11398
|
+
openAgentFactoryStatePr = async (ctx, _profile, agentResult) => {
|
|
11399
|
+
if (agentResult?.outcome !== "completed") {
|
|
11400
|
+
throw new Error(`openAgentFactoryStatePr: agent did not complete: ${agentResult?.error ?? "unknown failure"}`);
|
|
11401
|
+
}
|
|
11402
|
+
if (ctx.data.agentDone !== true) {
|
|
11403
|
+
throw new Error("openAgentFactoryStatePr: agent did not produce a successful final result");
|
|
11404
|
+
}
|
|
11405
|
+
if (!ctx.config.state?.repo || !ctx.config.state?.path) {
|
|
11406
|
+
throw new Error("openAgentFactoryStatePr: config.state.repo and config.state.path are required");
|
|
11407
|
+
}
|
|
11408
|
+
const issueNumber = readIssueNumber(ctx);
|
|
11409
|
+
const bundle = parseAgentFactoryBundle(String(ctx.data.prSummary ?? ""));
|
|
11410
|
+
const normalizedFiles = normalizeBundleFiles(ctx, bundle);
|
|
11411
|
+
const stateRepo = parseStateRepo(ctx.config);
|
|
11412
|
+
const baseBranch = "main";
|
|
11413
|
+
const branch = buildAgentFactoryBranchName(issueNumber, bundle.title);
|
|
11414
|
+
const baseRef = ghJson(["api", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/ref/heads/${baseBranch}`], ctx.cwd);
|
|
11415
|
+
const baseSha = requireString2(baseRef.object?.sha, `state repo ${stateRepo.owner}/${stateRepo.repo} ${baseBranch} ref sha`);
|
|
11416
|
+
const baseCommit = ghJson(
|
|
11417
|
+
["api", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/commits/${baseSha}`],
|
|
11418
|
+
ctx.cwd
|
|
11419
|
+
);
|
|
11420
|
+
const baseTreeSha = requireString2(baseCommit.tree?.sha, `state repo ${stateRepo.owner}/${stateRepo.repo} base tree sha`);
|
|
11421
|
+
ghJson(
|
|
11422
|
+
["api", "--method", "POST", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/refs`, "--input", "-"],
|
|
11423
|
+
ctx.cwd,
|
|
11424
|
+
{
|
|
11425
|
+
ref: `refs/heads/${branch}`,
|
|
11426
|
+
sha: baseSha
|
|
11427
|
+
}
|
|
11428
|
+
);
|
|
11429
|
+
const tree = ghJson(
|
|
11430
|
+
["api", "--method", "POST", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/trees`, "--input", "-"],
|
|
11431
|
+
ctx.cwd,
|
|
11432
|
+
{
|
|
11433
|
+
base_tree: baseTreeSha,
|
|
11434
|
+
tree: normalizedFiles.map((file) => ({
|
|
11435
|
+
path: file.targetPath,
|
|
11436
|
+
mode: "100644",
|
|
11437
|
+
type: "blob",
|
|
11438
|
+
content: file.content
|
|
11439
|
+
}))
|
|
11440
|
+
}
|
|
11441
|
+
);
|
|
11442
|
+
const treeSha = requireString2(tree.sha, "created tree sha");
|
|
11443
|
+
const commit = ghJson(
|
|
11444
|
+
["api", "--method", "POST", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/commits`, "--input", "-"],
|
|
11445
|
+
ctx.cwd,
|
|
11446
|
+
{
|
|
11447
|
+
message: `agent-factory: ${bundle.title}`,
|
|
11448
|
+
tree: treeSha,
|
|
11449
|
+
parents: [baseSha]
|
|
11450
|
+
}
|
|
11451
|
+
);
|
|
11452
|
+
const commitSha = requireString2(commit.sha, "created commit sha");
|
|
11453
|
+
ghJson(
|
|
11454
|
+
["api", "--method", "PATCH", `/repos/${stateRepo.owner}/${stateRepo.repo}/git/refs/heads/${branch}`, "--input", "-"],
|
|
11455
|
+
ctx.cwd,
|
|
11456
|
+
{
|
|
11457
|
+
sha: commitSha,
|
|
11458
|
+
force: false
|
|
11459
|
+
}
|
|
11460
|
+
);
|
|
11461
|
+
const pr = ghJson(
|
|
11462
|
+
["api", "--method", "POST", `/repos/${stateRepo.owner}/${stateRepo.repo}/pulls`, "--input", "-"],
|
|
11463
|
+
ctx.cwd,
|
|
11464
|
+
{
|
|
11465
|
+
title: `agent-factory: ${bundle.title}`,
|
|
11466
|
+
head: branch,
|
|
11467
|
+
base: baseBranch,
|
|
11468
|
+
body: renderPullRequestBody(ctx, bundle, normalizedFiles)
|
|
11469
|
+
}
|
|
11470
|
+
);
|
|
11471
|
+
const prUrl = requireString2(pr.html_url, "created pull request url");
|
|
11472
|
+
gh(["issue", "comment", String(issueNumber), "--body-file", "-"], {
|
|
11473
|
+
cwd: ctx.cwd,
|
|
11474
|
+
input: renderIssueComment(stateRepo.owner, stateRepo.repo, prUrl, bundle)
|
|
11475
|
+
});
|
|
11476
|
+
ctx.data.agentFactoryStatePr = {
|
|
11477
|
+
repo: `${stateRepo.owner}/${stateRepo.repo}`,
|
|
11478
|
+
branch,
|
|
11479
|
+
base: baseBranch,
|
|
11480
|
+
url: prUrl,
|
|
11481
|
+
number: pr.number,
|
|
11482
|
+
files: normalizedFiles.map((file) => file.targetPath)
|
|
11483
|
+
};
|
|
11484
|
+
ctx.output.prUrl = prUrl;
|
|
11485
|
+
};
|
|
11486
|
+
}
|
|
11487
|
+
});
|
|
11488
|
+
|
|
11255
11489
|
// src/scripts/openQaIssue.ts
|
|
11256
11490
|
function qaAction2(verdict, payload) {
|
|
11257
11491
|
const type = verdict === "PASS" ? "QA_PASS" : verdict === "CONCERNS" ? "QA_CONCERNS" : verdict === "FAIL" ? "QA_FAIL" : "QA_COMPLETED";
|
|
@@ -14394,6 +14628,7 @@ var init_scripts = __esm({
|
|
|
14394
14628
|
init_mergeReleasePr();
|
|
14395
14629
|
init_mirrorStateToPr();
|
|
14396
14630
|
init_notifyTerminal();
|
|
14631
|
+
init_openAgentFactoryStatePr();
|
|
14397
14632
|
init_openQaIssue();
|
|
14398
14633
|
init_parseAgentResult();
|
|
14399
14634
|
init_parseIssueStateFromAgentResult();
|
|
@@ -14523,6 +14758,7 @@ var init_scripts = __esm({
|
|
|
14523
14758
|
recordClassification,
|
|
14524
14759
|
dispatchClassified,
|
|
14525
14760
|
notifyTerminal,
|
|
14761
|
+
openAgentFactoryStatePr,
|
|
14526
14762
|
openQaIssue,
|
|
14527
14763
|
createQaGoal,
|
|
14528
14764
|
failOnceTaskJob,
|
|
@@ -15406,7 +15642,8 @@ var init_executor = __esm({
|
|
|
15406
15642
|
MUTATING_POSTFLIGHTS = /* @__PURE__ */ new Set([
|
|
15407
15643
|
"commitAndPush",
|
|
15408
15644
|
"ensurePr",
|
|
15409
|
-
"applyAgentResponsibilityReports"
|
|
15645
|
+
"applyAgentResponsibilityReports",
|
|
15646
|
+
"openAgentFactoryStatePr"
|
|
15410
15647
|
]);
|
|
15411
15648
|
MAX_CHAIN_HOPS = 60;
|
|
15412
15649
|
DEFAULT_SHELL_TIMEOUT_MS = 3e5;
|
|
@@ -16785,6 +17022,18 @@ function unpackAllSecrets(env = process.env) {
|
|
|
16785
17022
|
return count;
|
|
16786
17023
|
}
|
|
16787
17024
|
async function resolveAuthToken(env = process.env) {
|
|
17025
|
+
const creds = readAppCreds(env);
|
|
17026
|
+
if (creds) {
|
|
17027
|
+
try {
|
|
17028
|
+
const minted = await mintAppInstallationToken(creds);
|
|
17029
|
+
env.GH_TOKEN = minted;
|
|
17030
|
+
process.stdout.write("\u2192 kody: GH_TOKEN minted from GitHub App (KODY_APP_ID/KODY_APP_PRIVATE_KEY)\n");
|
|
17031
|
+
return minted;
|
|
17032
|
+
} catch (err) {
|
|
17033
|
+
process.stdout.write(`\u2192 kody: WARNING GitHub App token mint failed: ${err.message}
|
|
17034
|
+
`);
|
|
17035
|
+
}
|
|
17036
|
+
}
|
|
16788
17037
|
const sources = [
|
|
16789
17038
|
["KODY_TOKEN", env.KODY_TOKEN],
|
|
16790
17039
|
["GH_TOKEN", env.GH_TOKEN],
|
|
@@ -16799,18 +17048,6 @@ async function resolveAuthToken(env = process.env) {
|
|
|
16799
17048
|
`);
|
|
16800
17049
|
return token;
|
|
16801
17050
|
}
|
|
16802
|
-
const creds = readAppCreds(env);
|
|
16803
|
-
if (creds) {
|
|
16804
|
-
try {
|
|
16805
|
-
const minted = await mintAppInstallationToken(creds);
|
|
16806
|
-
env.GH_TOKEN = minted;
|
|
16807
|
-
process.stdout.write("\u2192 kody: GH_TOKEN minted from GitHub App (KODY_APP_ID/KODY_APP_PRIVATE_KEY)\n");
|
|
16808
|
-
return minted;
|
|
16809
|
-
} catch (err) {
|
|
16810
|
-
process.stdout.write(`\u2192 kody: WARNING GitHub App token mint failed: ${err.message}
|
|
16811
|
-
`);
|
|
16812
|
-
}
|
|
16813
|
-
}
|
|
16814
17051
|
process.stdout.write(
|
|
16815
17052
|
"\u2192 kody: WARNING no auth token found (KODY_TOKEN/GH_TOKEN/GITHUB_TOKEN/GH_PAT/GitHub App all empty)\n"
|
|
16816
17053
|
);
|
|
@@ -18232,7 +18469,7 @@ async function loadConfigSafe() {
|
|
|
18232
18469
|
quality: { typecheck: "", lint: "", format: "", testUnit: "" },
|
|
18233
18470
|
git: { defaultBranch: "main" },
|
|
18234
18471
|
github: { owner: "unknown", repo: "unknown" },
|
|
18235
|
-
state: { repo: "unknown/kody-state", path: "unknown" },
|
|
18472
|
+
state: { repo: "https://github.com/unknown/kody-state", path: "unknown" },
|
|
18236
18473
|
agent: { model: "claude/claude-sonnet-4" }
|
|
18237
18474
|
};
|
|
18238
18475
|
}
|
package/kody.config.schema.json
CHANGED
|
@@ -53,6 +53,22 @@
|
|
|
53
53
|
"repo": { "type": "string" }
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
+
"state": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"description": "External repository and path used for Kody runtime state.",
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"properties": {
|
|
61
|
+
"repo": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "Full GitHub repository URL for Kody runtime state.",
|
|
64
|
+
"pattern": "^https://github\\.com/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:\\.git)?$"
|
|
65
|
+
},
|
|
66
|
+
"path": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"description": "Folder inside state.repo that belongs to this consumer repo."
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
56
72
|
"agent": {
|
|
57
73
|
"type": "object",
|
|
58
74
|
"required": ["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.243",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative agentAction profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|