@kody-ade/kody-engine 0.4.638 → 0.4.640
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
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.640",
|
|
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
|
repository: {
|
|
@@ -180,49 +180,6 @@ var init_completionGuard = __esm({
|
|
|
180
180
|
}
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
// src/submitStateGuard.ts
|
|
184
|
-
function createSubmitStateActivityGuard() {
|
|
185
|
-
let hasActivity = false;
|
|
186
|
-
return {
|
|
187
|
-
recordToolUse: async (input) => {
|
|
188
|
-
if (input?.tool_name !== SUBMIT_STATE_TOOL) hasActivity = true;
|
|
189
|
-
return {};
|
|
190
|
-
},
|
|
191
|
-
requireActivity: async () => hasActivity ? {} : {
|
|
192
|
-
decision: "block",
|
|
193
|
-
reason: ACTIVITY_REQUIRED_REASON
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function createPostSubmitToolGuard(getSubmitted) {
|
|
198
|
-
return async () => getSubmitted() ? {
|
|
199
|
-
decision: "block",
|
|
200
|
-
reason: STATE_ALREADY_SUBMITTED_REASON
|
|
201
|
-
} : {};
|
|
202
|
-
}
|
|
203
|
-
function createSubmitStateStopHook(getSubmitted) {
|
|
204
|
-
let finalChanceGiven = false;
|
|
205
|
-
return async () => {
|
|
206
|
-
if (getSubmitted()) return {};
|
|
207
|
-
if (finalChanceGiven) return {};
|
|
208
|
-
finalChanceGiven = true;
|
|
209
|
-
return {
|
|
210
|
-
decision: "block",
|
|
211
|
-
reason: FINAL_STATE_CHANCE_REASON
|
|
212
|
-
};
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
var FINAL_STATE_CHANCE_REASON, STATE_ALREADY_SUBMITTED_REASON, ACTIVITY_REQUIRED_REASON, SUBMIT_STATE_TOOL;
|
|
216
|
-
var init_submitStateGuard = __esm({
|
|
217
|
-
"src/submitStateGuard.ts"() {
|
|
218
|
-
"use strict";
|
|
219
|
-
FINAL_STATE_CHANCE_REASON = "Before finishing, call `submit_state` exactly once with the next non-empty `cursor`, compact durable `data`, and the correct `done` value. Do not perform more work; submit only the continuation state now.";
|
|
220
|
-
STATE_ALREADY_SUBMITTED_REASON = "Continuation state is already submitted for this cycle. Do not call more tools or perform more work; return your final response now.";
|
|
221
|
-
ACTIVITY_REQUIRED_REASON = "Do not submit continuation state yet. First use a tool to observe current evidence or perform the next responsibility action for this cycle.";
|
|
222
|
-
SUBMIT_STATE_TOOL = "mcp__kody-submit__submit_state";
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
183
|
// src/config.ts
|
|
227
184
|
import * as fs2 from "fs";
|
|
228
185
|
import * as path3 from "path";
|
|
@@ -1193,6 +1150,49 @@ var init_subagents = __esm({
|
|
|
1193
1150
|
}
|
|
1194
1151
|
});
|
|
1195
1152
|
|
|
1153
|
+
// src/submitStateGuard.ts
|
|
1154
|
+
function createSubmitStateActivityGuard() {
|
|
1155
|
+
let hasActivity = false;
|
|
1156
|
+
return {
|
|
1157
|
+
recordToolUse: async (input) => {
|
|
1158
|
+
if (input?.tool_name !== SUBMIT_STATE_TOOL) hasActivity = true;
|
|
1159
|
+
return {};
|
|
1160
|
+
},
|
|
1161
|
+
requireActivity: async () => hasActivity ? {} : {
|
|
1162
|
+
decision: "block",
|
|
1163
|
+
reason: ACTIVITY_REQUIRED_REASON
|
|
1164
|
+
}
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
function createPostSubmitToolGuard(getSubmitted) {
|
|
1168
|
+
return async () => getSubmitted() ? {
|
|
1169
|
+
decision: "block",
|
|
1170
|
+
reason: STATE_ALREADY_SUBMITTED_REASON
|
|
1171
|
+
} : {};
|
|
1172
|
+
}
|
|
1173
|
+
function createSubmitStateStopHook(getSubmitted) {
|
|
1174
|
+
let finalChanceGiven = false;
|
|
1175
|
+
return async () => {
|
|
1176
|
+
if (getSubmitted()) return {};
|
|
1177
|
+
if (finalChanceGiven) return {};
|
|
1178
|
+
finalChanceGiven = true;
|
|
1179
|
+
return {
|
|
1180
|
+
decision: "block",
|
|
1181
|
+
reason: FINAL_STATE_CHANCE_REASON
|
|
1182
|
+
};
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
var FINAL_STATE_CHANCE_REASON, STATE_ALREADY_SUBMITTED_REASON, ACTIVITY_REQUIRED_REASON, SUBMIT_STATE_TOOL;
|
|
1186
|
+
var init_submitStateGuard = __esm({
|
|
1187
|
+
"src/submitStateGuard.ts"() {
|
|
1188
|
+
"use strict";
|
|
1189
|
+
FINAL_STATE_CHANCE_REASON = "Before finishing, call `submit_state` exactly once with the next non-empty `cursor`, compact durable `data`, and the correct `done` value. Do not perform more work; submit only the continuation state now.";
|
|
1190
|
+
STATE_ALREADY_SUBMITTED_REASON = "Continuation state is already submitted for this cycle. Do not call more tools or perform more work; return your final response now.";
|
|
1191
|
+
ACTIVITY_REQUIRED_REASON = "Do not submit continuation state yet. First use a tool to observe current evidence or perform the next responsibility action for this cycle.";
|
|
1192
|
+
SUBMIT_STATE_TOOL = "mcp__kody-submit__submit_state";
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1196
1196
|
// src/events.ts
|
|
1197
1197
|
var events_exports = {};
|
|
1198
1198
|
__export(events_exports, {
|
|
@@ -3589,10 +3589,19 @@ __export(capabilityMcp_exports, {
|
|
|
3589
3589
|
parseCapabilityTrustMode: () => parseCapabilityTrustMode,
|
|
3590
3590
|
readCheckRuns: () => readCheckRuns,
|
|
3591
3591
|
readThread: () => readThread,
|
|
3592
|
+
selectCapabilityToolDefinitions: () => selectCapabilityToolDefinitions,
|
|
3592
3593
|
startCapability: () => startCapability
|
|
3593
3594
|
});
|
|
3594
3595
|
import { createSdkMcpServer as createSdkMcpServer4, tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
|
|
3595
3596
|
import { z as z3 } from "zod";
|
|
3597
|
+
function selectCapabilityToolDefinitions(definitions, allowedToolNames) {
|
|
3598
|
+
if (!allowedToolNames) return definitions;
|
|
3599
|
+
const available = new Set(definitions.map((definition) => definition.name));
|
|
3600
|
+
const unknown = allowedToolNames.filter((name) => !available.has(name));
|
|
3601
|
+
if (unknown.length > 0) throw new Error(`Unknown capability MCP tools: ${unknown.join(", ")}`);
|
|
3602
|
+
const allowed = new Set(allowedToolNames);
|
|
3603
|
+
return definitions.filter((definition) => allowed.has(definition.name));
|
|
3604
|
+
}
|
|
3596
3605
|
function summarizeCiStatus(rollup) {
|
|
3597
3606
|
if (!Array.isArray(rollup) || rollup.length === 0) return "UNKNOWN";
|
|
3598
3607
|
let hasRunning = false;
|
|
@@ -4099,46 +4108,71 @@ function capabilityToolDefinitions(opts) {
|
|
|
4099
4108
|
const reportRunId = typeof args.reportRunId === "string" ? args.reportRunId : void 0;
|
|
4100
4109
|
const evidence = typeof args.evidence === "string" ? args.evidence.trim() : "";
|
|
4101
4110
|
const backend = createStateBackendFromEnv();
|
|
4102
|
-
const existing = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4103
4111
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4104
|
-
const current = existing?.doc && typeof existing.doc === "object" && !Array.isArray(existing.doc) ? existing.doc : {};
|
|
4105
|
-
const currentItems = Array.isArray(current.items) ? current.items.filter((item) => Boolean(item && typeof item === "object" && !Array.isArray(item))) : [];
|
|
4106
|
-
const previous = currentItems.find((item) => item.id === itemId);
|
|
4107
4112
|
const completed = status === "resolved";
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4113
|
+
let lastError = new Error(`Todo ${slug}/${itemId} was not visible after reconciliation`);
|
|
4114
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
4115
|
+
try {
|
|
4116
|
+
const existing = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4117
|
+
const current = existing?.doc && typeof existing.doc === "object" && !Array.isArray(existing.doc) ? existing.doc : {};
|
|
4118
|
+
const currentItems = Array.isArray(current.items) ? current.items.filter(
|
|
4119
|
+
(item) => Boolean(item && typeof item === "object" && !Array.isArray(item))
|
|
4120
|
+
) : [];
|
|
4121
|
+
const previous = currentItems.find((item) => item.id === itemId);
|
|
4122
|
+
const previousMeta = previous?.meta && typeof previous.meta === "object" && !Array.isArray(previous.meta) ? previous.meta : {};
|
|
4123
|
+
const unchanged = Boolean(
|
|
4124
|
+
previous && previous.completed === completed && previous.title === title && String(previous.body ?? "") === evidence && previousMeta.reportSlug === reportSlug
|
|
4125
|
+
);
|
|
4126
|
+
if (unchanged) {
|
|
4127
|
+
return {
|
|
4128
|
+
content: [{ type: "text", text: JSON.stringify({ changed: false, verified: true, slug, status }) }]
|
|
4129
|
+
};
|
|
4130
|
+
}
|
|
4131
|
+
const nextItem = {
|
|
4132
|
+
id: itemId,
|
|
4133
|
+
title,
|
|
4134
|
+
body: evidence,
|
|
4135
|
+
assignee: null,
|
|
4136
|
+
completed,
|
|
4137
|
+
createdAt: typeof previous?.createdAt === "string" ? previous.createdAt : now,
|
|
4138
|
+
completedAt: completed ? now : null,
|
|
4139
|
+
meta: {
|
|
4140
|
+
...previousMeta,
|
|
4141
|
+
source: "live-agent",
|
|
4142
|
+
reportSlug,
|
|
4143
|
+
...reportRunId ? { reportRunId } : {},
|
|
4144
|
+
status
|
|
4145
|
+
}
|
|
4146
|
+
};
|
|
4147
|
+
const items = previous ? currentItems.map((item) => item.id === itemId ? nextItem : item) : [...currentItems, nextItem];
|
|
4148
|
+
const doc = {
|
|
4149
|
+
...current,
|
|
4150
|
+
version: 1,
|
|
4151
|
+
title,
|
|
4152
|
+
description,
|
|
4153
|
+
createdAt: typeof current.createdAt === "string" ? current.createdAt : now,
|
|
4154
|
+
items
|
|
4155
|
+
};
|
|
4156
|
+
await backend.saveRepoDoc(opts.repoSlug, `todo:${slug}`, doc, existing?.updatedAt);
|
|
4157
|
+
const saved = await backend.getRepoDoc(opts.repoSlug, `todo:${slug}`);
|
|
4158
|
+
const savedItems = saved?.doc && typeof saved.doc === "object" && !Array.isArray(saved.doc) && Array.isArray(saved.doc.items) ? saved.doc.items : [];
|
|
4159
|
+
const savedItem = savedItems.find(
|
|
4160
|
+
(item) => Boolean(
|
|
4161
|
+
item && typeof item === "object" && !Array.isArray(item) && item.id === itemId
|
|
4162
|
+
)
|
|
4163
|
+
);
|
|
4164
|
+
const savedMeta = savedItem?.meta && typeof savedItem.meta === "object" && !Array.isArray(savedItem.meta) ? savedItem.meta : {};
|
|
4165
|
+
if (savedItem && savedItem.completed === completed && savedItem.title === title && String(savedItem.body ?? "") === evidence && savedMeta.reportSlug === reportSlug) {
|
|
4166
|
+
return {
|
|
4167
|
+
content: [{ type: "text", text: JSON.stringify({ changed: true, verified: true, slug, status }) }]
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
4170
|
+
lastError = new Error(`Todo ${slug}/${itemId} was not visible after reconciliation attempt ${attempt + 1}`);
|
|
4171
|
+
} catch (error) {
|
|
4172
|
+
lastError = error;
|
|
4129
4173
|
}
|
|
4130
|
-
}
|
|
4131
|
-
|
|
4132
|
-
const doc = {
|
|
4133
|
-
...current,
|
|
4134
|
-
version: 1,
|
|
4135
|
-
title,
|
|
4136
|
-
description,
|
|
4137
|
-
createdAt: typeof current.createdAt === "string" ? current.createdAt : now,
|
|
4138
|
-
items
|
|
4139
|
-
};
|
|
4140
|
-
await backend.saveRepoDoc(opts.repoSlug, `todo:${slug}`, doc, existing?.updatedAt);
|
|
4141
|
-
return { content: [{ type: "text", text: JSON.stringify({ changed: true, slug, status }) }] };
|
|
4174
|
+
}
|
|
4175
|
+
throw lastError;
|
|
4142
4176
|
}
|
|
4143
4177
|
};
|
|
4144
4178
|
const cmsTools = dashboardCmsToolDefinitions({
|
|
@@ -4163,7 +4197,7 @@ function capabilityToolDefinitions(opts) {
|
|
|
4163
4197
|
];
|
|
4164
4198
|
}
|
|
4165
4199
|
function buildCapabilityMcpServer(opts) {
|
|
4166
|
-
const definitions = capabilityToolDefinitions(opts);
|
|
4200
|
+
const definitions = selectCapabilityToolDefinitions(capabilityToolDefinitions(opts), opts.allowedToolNames);
|
|
4167
4201
|
const tools = definitions.map(
|
|
4168
4202
|
(def) => tool4(
|
|
4169
4203
|
def.name,
|
|
@@ -4186,8 +4220,8 @@ var init_capabilityMcp = __esm({
|
|
|
4186
4220
|
init_dashboardCmsMcp();
|
|
4187
4221
|
init_issue();
|
|
4188
4222
|
init_registry();
|
|
4189
|
-
init_trustPolicy();
|
|
4190
4223
|
init_state_backend();
|
|
4224
|
+
init_trustPolicy();
|
|
4191
4225
|
FAIL_CONCLUSIONS = /* @__PURE__ */ new Set(["FAILURE", "TIMED_OUT", "ACTION_REQUIRED", "STARTUP_FAILURE", "CANCELLED"]);
|
|
4192
4226
|
RUNNING_STATUSES = /* @__PURE__ */ new Set(["IN_PROGRESS", "QUEUED", "PENDING", "WAITING", "REQUESTED"]);
|
|
4193
4227
|
THREAD_BODY_MAX = 4e3;
|
|
@@ -4588,6 +4622,7 @@ async function runAgent(opts) {
|
|
|
4588
4622
|
const capabilityHandle = buildCapabilityMcpServer2({
|
|
4589
4623
|
repoSlug: opts.capabilityRepoSlug,
|
|
4590
4624
|
operatorMention: opts.capabilityOperatorMention ?? "",
|
|
4625
|
+
...opts.capabilityToolNames ? { allowedToolNames: opts.capabilityToolNames } : {},
|
|
4591
4626
|
...opts.capabilityDefaultBranch ? { defaultBranch: opts.capabilityDefaultBranch } : {},
|
|
4592
4627
|
...opts.capabilitySlug ? { capabilitySlug: opts.capabilitySlug } : {}
|
|
4593
4628
|
});
|
|
@@ -4904,13 +4939,13 @@ var init_agent = __esm({
|
|
|
4904
4939
|
"use strict";
|
|
4905
4940
|
init_claudeBinary();
|
|
4906
4941
|
init_completionGuard();
|
|
4907
|
-
init_submitStateGuard();
|
|
4908
4942
|
init_config();
|
|
4909
4943
|
init_fileEditGuards();
|
|
4910
4944
|
init_format();
|
|
4911
4945
|
init_outputContractHooks();
|
|
4912
4946
|
init_runtimePaths();
|
|
4913
4947
|
init_subagents();
|
|
4948
|
+
init_submitStateGuard();
|
|
4914
4949
|
DEFAULT_ALLOWED_TOOLS = ["Bash", "Edit", "Read", "Write", "Glob", "Grep"];
|
|
4915
4950
|
DEFAULT_TURN_TIMEOUT_MS = 6e5;
|
|
4916
4951
|
MAX_CONNECTION_RETRIES = 2;
|
|
@@ -23396,6 +23431,7 @@ async function runImplementation(profileName, input) {
|
|
|
23396
23431
|
// to know the palette — it just forwards the flag so agent.ts can spin
|
|
23397
23432
|
// up the in-process `kody-capability` MCP server with the right context.
|
|
23398
23433
|
enableCapabilityTool: Array.isArray(ctx.data.capabilityTools) && ctx.data.capabilityTools.length > 0,
|
|
23434
|
+
capabilityToolNames: Array.isArray(ctx.data.capabilityTools) ? ctx.data.capabilityTools.filter((name) => typeof name === "string") : void 0,
|
|
23399
23435
|
enableDashboardCmsTool: Boolean(
|
|
23400
23436
|
ctx.data.capabilityRequirements && typeof ctx.data.capabilityRequirements === "object" && !Array.isArray(ctx.data.capabilityRequirements) && ctx.data.capabilityRequirements.cms === true
|
|
23401
23437
|
),
|
|
File without changes
|
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.640",
|
|
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
|
"repository": {
|
|
@@ -17,6 +17,30 @@
|
|
|
17
17
|
"docs/delivery-boundary.md",
|
|
18
18
|
"kody.config.schema.json"
|
|
19
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"kody:run": "tsx bin/kody.ts",
|
|
22
|
+
"serve": "tsx bin/kody.ts serve",
|
|
23
|
+
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
24
|
+
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
25
|
+
"clean:dist": "node scripts/clean-dist.cjs",
|
|
26
|
+
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
27
|
+
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
28
|
+
"pretest": "pnpm check:modularity",
|
|
29
|
+
"test": "vitest run tests/unit tests/int --coverage",
|
|
30
|
+
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
31
|
+
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
32
|
+
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
33
|
+
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
34
|
+
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
35
|
+
"test:all": "vitest run tests --no-coverage",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"lint": "biome check",
|
|
38
|
+
"lint:fix": "biome check --write",
|
|
39
|
+
"format": "biome format --write",
|
|
40
|
+
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
41
|
+
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner",
|
|
42
|
+
"prepublishOnly": "pnpm typecheck && pnpm test:runtime-services && pnpm build && pnpm verify:package"
|
|
43
|
+
},
|
|
20
44
|
"dependencies": {
|
|
21
45
|
"@actions/cache": "^6.0.0",
|
|
22
46
|
"@anthropic-ai/claude-agent-sdk": "0.2.119",
|
|
@@ -39,28 +63,5 @@
|
|
|
39
63
|
"node": ">=22"
|
|
40
64
|
},
|
|
41
65
|
"homepage": "https://github.com/aharonyaircohen/kody-engine",
|
|
42
|
-
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
43
|
-
|
|
44
|
-
"kody:run": "tsx bin/kody.ts",
|
|
45
|
-
"serve": "tsx bin/kody.ts serve",
|
|
46
|
-
"serve:vscode": "tsx bin/kody.ts serve vscode",
|
|
47
|
-
"serve:claude": "tsx bin/kody.ts serve claude",
|
|
48
|
-
"clean:dist": "node scripts/clean-dist.cjs",
|
|
49
|
-
"build": "pnpm clean:dist && tsup && node scripts/copy-assets.cjs",
|
|
50
|
-
"check:modularity": "tsx scripts/check-script-modularity.ts",
|
|
51
|
-
"pretest": "pnpm check:modularity",
|
|
52
|
-
"test": "vitest run tests/unit tests/int --coverage",
|
|
53
|
-
"posttest": "tsx scripts/check-coverage-floor.ts",
|
|
54
|
-
"test:smoke": "vitest run tests/smoke --no-coverage",
|
|
55
|
-
"test:e2e": "vitest run tests/e2e --no-coverage",
|
|
56
|
-
"verify:live-release": "tsx scripts/live-release-gate.ts",
|
|
57
|
-
"test:runtime-services": "node --test \"tests/runtime-services/*.test.mjs\"",
|
|
58
|
-
"test:all": "vitest run tests --no-coverage",
|
|
59
|
-
"typecheck": "tsc --noEmit",
|
|
60
|
-
"lint": "biome check",
|
|
61
|
-
"lint:fix": "biome check --write",
|
|
62
|
-
"format": "biome format --write",
|
|
63
|
-
"verify:package": "node scripts/verify-package-tarball.cjs",
|
|
64
|
-
"brain:publish": "docker buildx build --platform linux/amd64 -f runner/Dockerfile.brain --build-arg KODY_ENGINE_REF=$(git rev-parse HEAD) -t ghcr.io/${KODY_BRAIN_GHCR_OWNER:-aharonyaircohen}/kody-brain:latest --push runner"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
66
|
+
"bugs": "https://github.com/aharonyaircohen/kody-engine/issues"
|
|
67
|
+
}
|