@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.
@@ -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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "agent-factory",
3
+ "action": "agent-factory",
4
+ "agentAction": "agent-factory",
5
+ "capabilityKind": "act",
6
+ "describe": "Create or assemble Kody agency model definitions from an operator request."
7
+ }
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.241",
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
- const parts = value.split("/");
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 look like "owner/repo"`);
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() : `${String(github.owner)}/kody-state`;
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
  }
@@ -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.241",
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",