@kody-ade/kody-engine 0.4.606 → 0.4.610
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/README.md +1 -1
- package/dist/bin/kody.js +297 -216
- package/dist/capabilities/live-agent/capability.md +9 -0
- package/dist/capabilities/live-agent/definition.json +32 -0
- package/dist/implementations/live-agent/profile.json +30 -0
- package/dist/implementations/live-agent/prompt.md +38 -0
- package/package.json +1 -1
- package/templates/kody.yml +1 -3
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ model key at runtime; user secrets are not copied into Actions. `KODY_TOKEN`
|
|
|
113
113
|
remains an optional GitHub authentication fallback when Kody must trigger
|
|
114
114
|
downstream workflows or modify `.github/workflows/*`.
|
|
115
115
|
|
|
116
|
-
The consumer workflow listens on `issue_comment` for `@kody ...` dispatch and `workflow_dispatch` for manual runs
|
|
116
|
+
The consumer workflow listens on `issue_comment` for `@kody ...` dispatch and `workflow_dispatch` for manual runs and chat mode. Convex owns scheduled Loop wakeups.
|
|
117
117
|
|
|
118
118
|
## Commands
|
|
119
119
|
|
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.610",
|
|
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",
|
|
@@ -2353,7 +2353,7 @@ function parseCapabilityRequirements(raw) {
|
|
|
2353
2353
|
if (raw === void 0) return void 0;
|
|
2354
2354
|
if (!isPlainObject(raw)) throw new Error("contract.json requirements must be an object");
|
|
2355
2355
|
const unsupported = Object.keys(raw).filter(
|
|
2356
|
-
(key) => key !== "browser" && key !== "qaCredentials" && key !== "githubTestToken" && key !== "qaAccountCredentials" && key !== "browserOnly"
|
|
2356
|
+
(key) => key !== "browser" && key !== "qaCredentials" && key !== "githubTestToken" && key !== "qaAccountCredentials" && key !== "qaAccountModelSettings" && key !== "browserOnly"
|
|
2357
2357
|
);
|
|
2358
2358
|
if (unsupported.length > 0) {
|
|
2359
2359
|
throw new Error(`contract.json requirements contains unsupported fields: ${unsupported.join(", ")}`);
|
|
@@ -2372,10 +2372,13 @@ function parseCapabilityRequirements(raw) {
|
|
|
2372
2372
|
))) {
|
|
2373
2373
|
throw new Error("contract.json requirements.qaAccountCredentials must contain valid credential names");
|
|
2374
2374
|
}
|
|
2375
|
+
if (raw.qaAccountModelSettings !== void 0 && !isPlainObject(raw.qaAccountModelSettings)) {
|
|
2376
|
+
throw new Error("contract.json requirements.qaAccountModelSettings must be an object");
|
|
2377
|
+
}
|
|
2375
2378
|
if (raw.browserOnly !== void 0 && typeof raw.browserOnly !== "boolean") {
|
|
2376
2379
|
throw new Error("contract.json requirements.browserOnly must be boolean");
|
|
2377
2380
|
}
|
|
2378
|
-
if ((raw.qaCredentials === true || raw.githubTestToken === true || raw.qaAccountCredentials !== void 0 || raw.browserOnly === true) && raw.browser !== true) {
|
|
2381
|
+
if ((raw.qaCredentials === true || raw.githubTestToken === true || raw.qaAccountCredentials !== void 0 || raw.qaAccountModelSettings !== void 0 || raw.browserOnly === true) && raw.browser !== true) {
|
|
2379
2382
|
throw new Error("contract.json authentication requirements require browser");
|
|
2380
2383
|
}
|
|
2381
2384
|
const requirements = {
|
|
@@ -2383,6 +2386,7 @@ function parseCapabilityRequirements(raw) {
|
|
|
2383
2386
|
...raw.qaCredentials === true ? { qaCredentials: true } : {},
|
|
2384
2387
|
...raw.githubTestToken === true ? { githubTestToken: true } : {},
|
|
2385
2388
|
...Array.isArray(raw.qaAccountCredentials) ? { qaAccountCredentials: [...new Set(raw.qaAccountCredentials)] } : {},
|
|
2389
|
+
...isPlainObject(raw.qaAccountModelSettings) ? { qaAccountModelSettings: raw.qaAccountModelSettings } : {},
|
|
2386
2390
|
...raw.browserOnly === true ? { browserOnly: true } : {}
|
|
2387
2391
|
};
|
|
2388
2392
|
return Object.keys(requirements).length > 0 ? requirements : void 0;
|
|
@@ -3154,6 +3158,13 @@ function createStateBackendFromEnv(env = process.env, client) {
|
|
|
3154
3158
|
});
|
|
3155
3159
|
return Array.isArray(result) ? result : [];
|
|
3156
3160
|
},
|
|
3161
|
+
async replaceLoopWakeRegistrations(tenantId2, loopIds, updatedAt) {
|
|
3162
|
+
await transport.mutation(anyApi.loopWakes.replaceRegistrations, {
|
|
3163
|
+
tenantId: requireTenant(tenantId2),
|
|
3164
|
+
loopIds: [...new Set(loopIds.map((id) => requireNonEmpty(id, "loopId")))],
|
|
3165
|
+
updatedAt: requireNonEmpty(updatedAt, "updatedAt")
|
|
3166
|
+
});
|
|
3167
|
+
},
|
|
3157
3168
|
async get(tenantId2, taskKey, kind) {
|
|
3158
3169
|
const result = await transport.query(anyApi.taskState.get, {
|
|
3159
3170
|
tenantId: requireTenant(tenantId2),
|
|
@@ -3172,6 +3183,26 @@ function createStateBackendFromEnv(env = process.env, client) {
|
|
|
3172
3183
|
...expectedUpdatedAt ? { expectedUpdatedAt } : {}
|
|
3173
3184
|
});
|
|
3174
3185
|
},
|
|
3186
|
+
async getAgentState(tenantId2, agent) {
|
|
3187
|
+
const result = await transport.query(anyApi.agentStates.get, {
|
|
3188
|
+
tenantId: requireTenant(tenantId2),
|
|
3189
|
+
agent: requireNonEmpty(agent, "agent")
|
|
3190
|
+
});
|
|
3191
|
+
return result ?? null;
|
|
3192
|
+
},
|
|
3193
|
+
async saveAgentState(tenantId2, state, expectedRevision) {
|
|
3194
|
+
await transport.mutation(anyApi.agentStates.save, {
|
|
3195
|
+
tenantId: requireTenant(tenantId2),
|
|
3196
|
+
state,
|
|
3197
|
+
...expectedRevision === void 0 ? {} : { expectedRevision }
|
|
3198
|
+
});
|
|
3199
|
+
},
|
|
3200
|
+
async resetAgentState(tenantId2, agent) {
|
|
3201
|
+
await transport.mutation(anyApi.agentStates.reset, {
|
|
3202
|
+
tenantId: requireTenant(tenantId2),
|
|
3203
|
+
agent: requireNonEmpty(agent, "agent")
|
|
3204
|
+
});
|
|
3205
|
+
},
|
|
3175
3206
|
async getRepoDoc(tenantId2, kind) {
|
|
3176
3207
|
const result = await transport.query(anyApi.repoDocs.get, {
|
|
3177
3208
|
tenantId: requireTenant(tenantId2),
|
|
@@ -14582,6 +14613,18 @@ function mergeLoopDefinitions(repositoryLoops, runtimeLoops) {
|
|
|
14582
14613
|
}
|
|
14583
14614
|
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
14584
14615
|
}
|
|
14616
|
+
function loopWakeRegistrationIds(loops) {
|
|
14617
|
+
return loops.filter((loop) => loop.enabled && loop.trigger.type === "schedule").map((loop) => loop.id).sort();
|
|
14618
|
+
}
|
|
14619
|
+
async function syncLoopWakeRegistrations(backend, tenantId2, loops, updatedAt, log2) {
|
|
14620
|
+
try {
|
|
14621
|
+
await backend.replaceLoopWakeRegistrations(tenantId2, loopWakeRegistrationIds(loops), updatedAt);
|
|
14622
|
+
return true;
|
|
14623
|
+
} catch {
|
|
14624
|
+
log2("\u2192 kody: Convex Loop wake registration backfill skipped; existing Loop execution continues");
|
|
14625
|
+
return false;
|
|
14626
|
+
}
|
|
14627
|
+
}
|
|
14585
14628
|
function loopDispatchSlot(loop, now, force, nonce) {
|
|
14586
14629
|
return force ? `manual:${now.toISOString()}:${nonce}` : dueSlot(loop, now);
|
|
14587
14630
|
}
|
|
@@ -14643,6 +14686,14 @@ var init_dispatchLoops = __esm({
|
|
|
14643
14686
|
const requestedLoopId = typeof ctx.args.loop === "string" ? ctx.args.loop.trim() : "";
|
|
14644
14687
|
const backend = createStateBackendFromEnv();
|
|
14645
14688
|
const loops = mergeLoopDefinitions(listLoopDefinitions(ctx.cwd), await backend.listLoops(tenantId2));
|
|
14689
|
+
await syncLoopWakeRegistrations(
|
|
14690
|
+
backend,
|
|
14691
|
+
tenantId2,
|
|
14692
|
+
loops,
|
|
14693
|
+
now.toISOString(),
|
|
14694
|
+
(message) => process.stderr.write(`${message}
|
|
14695
|
+
`)
|
|
14696
|
+
);
|
|
14646
14697
|
const due = selectRunnableLoops(loops, now, {
|
|
14647
14698
|
force,
|
|
14648
14699
|
...requestedLoopId ? { loopId: requestedLoopId } : {}
|
|
@@ -16438,14 +16489,105 @@ ${truncate2(issue2.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
16438
16489
|
}
|
|
16439
16490
|
});
|
|
16440
16491
|
|
|
16441
|
-
// src/scripts/
|
|
16492
|
+
// src/scripts/loadLiveAgent.ts
|
|
16442
16493
|
import * as fs43 from "fs";
|
|
16494
|
+
function tenant(config) {
|
|
16495
|
+
const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY ?? "").split("/");
|
|
16496
|
+
const owner = config.github?.owner?.trim() || envOwner;
|
|
16497
|
+
const repo = config.github?.repo?.trim() || envRepo;
|
|
16498
|
+
if (!owner || !repo) throw new Error("Repository identity is required for live Agent execution");
|
|
16499
|
+
return `${owner}/${repo}`;
|
|
16500
|
+
}
|
|
16501
|
+
function frontmatter(raw) {
|
|
16502
|
+
const match = /^---\n([\s\S]*?)\n---/.exec(raw);
|
|
16503
|
+
if (!match) return {};
|
|
16504
|
+
const result = {};
|
|
16505
|
+
for (const line of match[1].split("\n")) {
|
|
16506
|
+
const at = line.indexOf(":");
|
|
16507
|
+
if (at < 0) continue;
|
|
16508
|
+
const key = line.slice(0, at).trim();
|
|
16509
|
+
const value = line.slice(at + 1).trim();
|
|
16510
|
+
result[key] = value.startsWith("[") ? value.slice(1, -1).split(",").map((entry) => entry.trim()).filter(Boolean) : value;
|
|
16511
|
+
}
|
|
16512
|
+
return result;
|
|
16513
|
+
}
|
|
16514
|
+
function guidanceBody(row, agent) {
|
|
16515
|
+
if (typeof row.doc?.body !== "string") return null;
|
|
16516
|
+
const metadata = frontmatter(row.doc.body);
|
|
16517
|
+
const audience = Array.isArray(metadata.agent) ? metadata.agent : [metadata.agent ?? "*"];
|
|
16518
|
+
if (!audience.includes("*") && !audience.includes(agent)) return null;
|
|
16519
|
+
return row.doc.body.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
16520
|
+
}
|
|
16521
|
+
function intentBody(row) {
|
|
16522
|
+
if (typeof row.doc?.body !== "string") return null;
|
|
16523
|
+
return row.doc.body.replace(/^---\n[\s\S]*?\n---\n?/, "").trim() || null;
|
|
16524
|
+
}
|
|
16525
|
+
var loadLiveAgent;
|
|
16526
|
+
var init_loadLiveAgent = __esm({
|
|
16527
|
+
"src/scripts/loadLiveAgent.ts"() {
|
|
16528
|
+
"use strict";
|
|
16529
|
+
init_definition_paths();
|
|
16530
|
+
init_agents();
|
|
16531
|
+
init_state_backend();
|
|
16532
|
+
loadLiveAgent = async (ctx, profile) => {
|
|
16533
|
+
const agent = String(ctx.args.agent ?? ctx.data.jobAgent ?? "").trim();
|
|
16534
|
+
if (!agent) throw new Error("loadLiveAgent: agent is required");
|
|
16535
|
+
const file = resolveAgentFile2(ctx.cwd, agent, agentsRoot(ctx.cwd));
|
|
16536
|
+
const raw = fs43.existsSync(file) ? fs43.readFileSync(file, "utf8") : "";
|
|
16537
|
+
const metadata = frontmatter(raw);
|
|
16538
|
+
const assignedIntent = typeof metadata.primaryIntent === "string" ? metadata.primaryIntent : "";
|
|
16539
|
+
const requestedIntent = String(ctx.args.intent ?? "").trim();
|
|
16540
|
+
const intent = requestedIntent || assignedIntent;
|
|
16541
|
+
if (!intent || requestedIntent && assignedIntent !== requestedIntent) {
|
|
16542
|
+
throw new Error(`Live Agent '${agent}' does not have the requested primary Intent`);
|
|
16543
|
+
}
|
|
16544
|
+
const backend = createStateBackendFromEnv();
|
|
16545
|
+
const tenantId2 = tenant(ctx.config);
|
|
16546
|
+
const [stateRow, intentRow, policies, constraints, context] = await Promise.all([
|
|
16547
|
+
backend.getAgentState(tenantId2, agent),
|
|
16548
|
+
backend.getRepoDoc(tenantId2, `intent:${intent}`),
|
|
16549
|
+
backend.listRepoDocs(tenantId2, "policy:"),
|
|
16550
|
+
backend.listRepoDocs(tenantId2, "constraint:"),
|
|
16551
|
+
backend.listRepoDocs(tenantId2, "context:")
|
|
16552
|
+
]);
|
|
16553
|
+
if (!stateRow) throw new Error(`Live Agent '${agent}' has no AgentState`);
|
|
16554
|
+
const state = stateRow.state;
|
|
16555
|
+
const selectedIntentBody = intentRow ? intentBody(intentRow) : null;
|
|
16556
|
+
if (!selectedIntentBody) throw new Error(`Primary Intent '${intent}' is missing`);
|
|
16557
|
+
const render = (rows) => rows.map((row) => guidanceBody(row, agent)).filter(Boolean).join("\n\n") || "None assigned.";
|
|
16558
|
+
ctx.data.agentIdentity = loadAgentIdentity(ctx.cwd, agent);
|
|
16559
|
+
ctx.data.liveAgentIntent = selectedIntentBody;
|
|
16560
|
+
ctx.data.liveAgentPolicies = render(policies);
|
|
16561
|
+
ctx.data.liveAgentConstraints = render(constraints);
|
|
16562
|
+
ctx.data.liveAgentContext = render(context);
|
|
16563
|
+
ctx.data.liveAgentCapabilities = Array.isArray(metadata.capabilities) ? metadata.capabilities.map((slug) => `- ${slug}`).join("\n") : "None assigned.";
|
|
16564
|
+
ctx.data.liveAgentSlug = agent;
|
|
16565
|
+
ctx.data.liveAgentPreviousRevision = Number(state.revision ?? 0);
|
|
16566
|
+
ctx.data.jobState = {
|
|
16567
|
+
state: {
|
|
16568
|
+
version: 1,
|
|
16569
|
+
rev: Number(state.revision ?? 0),
|
|
16570
|
+
cursor: String(state.cursor ?? "idle"),
|
|
16571
|
+
data: state.data ?? {},
|
|
16572
|
+
done: false
|
|
16573
|
+
}
|
|
16574
|
+
};
|
|
16575
|
+
ctx.data.jobStateJson = JSON.stringify(state, null, 2);
|
|
16576
|
+
ctx.data.capabilityTools = ["start_capability"];
|
|
16577
|
+
ctx.data.capabilityToolMode = "lock";
|
|
16578
|
+
profile.claudeCode.enableSubmitTool = true;
|
|
16579
|
+
};
|
|
16580
|
+
}
|
|
16581
|
+
});
|
|
16582
|
+
|
|
16583
|
+
// src/scripts/kodyVariables.ts
|
|
16584
|
+
import * as fs44 from "fs";
|
|
16443
16585
|
import * as path41 from "path";
|
|
16444
16586
|
function readKodyVariables(cwd) {
|
|
16445
16587
|
const full = path41.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
16446
16588
|
let raw;
|
|
16447
16589
|
try {
|
|
16448
|
-
raw =
|
|
16590
|
+
raw = fs44.readFileSync(full, "utf-8");
|
|
16449
16591
|
} catch {
|
|
16450
16592
|
return {};
|
|
16451
16593
|
}
|
|
@@ -16470,7 +16612,7 @@ var init_kodyVariables = __esm({
|
|
|
16470
16612
|
});
|
|
16471
16613
|
|
|
16472
16614
|
// src/scripts/loadQaContext.ts
|
|
16473
|
-
import * as
|
|
16615
|
+
import * as fs45 from "fs";
|
|
16474
16616
|
import * as path42 from "path";
|
|
16475
16617
|
function parseSlugList(value) {
|
|
16476
16618
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
@@ -16501,17 +16643,17 @@ function readProfileAgents(raw) {
|
|
|
16501
16643
|
}
|
|
16502
16644
|
function readProfile(cwd) {
|
|
16503
16645
|
const dir = path42.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
16504
|
-
if (!
|
|
16646
|
+
if (!fs45.existsSync(dir)) return "";
|
|
16505
16647
|
let entries;
|
|
16506
16648
|
try {
|
|
16507
|
-
entries =
|
|
16649
|
+
entries = fs45.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
16508
16650
|
} catch {
|
|
16509
16651
|
return "";
|
|
16510
16652
|
}
|
|
16511
16653
|
const blocks = [];
|
|
16512
16654
|
for (const file of entries) {
|
|
16513
16655
|
try {
|
|
16514
|
-
const raw =
|
|
16656
|
+
const raw = fs45.readFileSync(path42.join(dir, file), "utf-8");
|
|
16515
16657
|
const { agent, body } = readProfileAgents(raw);
|
|
16516
16658
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
16517
16659
|
blocks.push(`## ${file}
|
|
@@ -16561,7 +16703,7 @@ var init_loadQaContext = __esm({
|
|
|
16561
16703
|
|
|
16562
16704
|
// src/scripts/loadSimpleCapability.ts
|
|
16563
16705
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
16564
|
-
import * as
|
|
16706
|
+
import * as fs46 from "fs";
|
|
16565
16707
|
import * as os6 from "os";
|
|
16566
16708
|
import * as path43 from "path";
|
|
16567
16709
|
function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
|
|
@@ -16576,7 +16718,7 @@ function registerCapabilitySubagents(profile, toolRoot, toolFiles) {
|
|
|
16576
16718
|
profile.subagentTemplates = {
|
|
16577
16719
|
...profile.subagentTemplates ?? {},
|
|
16578
16720
|
...Object.fromEntries(
|
|
16579
|
-
subagentFiles.map(({ name, file }) => [name,
|
|
16721
|
+
subagentFiles.map(({ name, file }) => [name, fs46.readFileSync(path43.join(toolRoot, file), "utf-8")])
|
|
16580
16722
|
)
|
|
16581
16723
|
};
|
|
16582
16724
|
if (!profile.claudeCode.tools.includes("Agent")) {
|
|
@@ -16617,10 +16759,10 @@ function scalar(value) {
|
|
|
16617
16759
|
return value;
|
|
16618
16760
|
}
|
|
16619
16761
|
function listFiles(root) {
|
|
16620
|
-
if (!
|
|
16762
|
+
if (!fs46.existsSync(root)) return [];
|
|
16621
16763
|
const files = [];
|
|
16622
16764
|
const visit = (dir) => {
|
|
16623
|
-
for (const entry of
|
|
16765
|
+
for (const entry of fs46.readdirSync(dir, { withFileTypes: true })) {
|
|
16624
16766
|
const absolute = path43.join(dir, entry.name);
|
|
16625
16767
|
if (entry.isSymbolicLink()) continue;
|
|
16626
16768
|
if (entry.isDirectory()) visit(absolute);
|
|
@@ -16712,7 +16854,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
16712
16854
|
...skillFiles.flatMap((file) => [
|
|
16713
16855
|
`### ${file}`,
|
|
16714
16856
|
"",
|
|
16715
|
-
|
|
16857
|
+
fs46.readFileSync(path43.join(skillRoot, file), "utf-8"),
|
|
16716
16858
|
""
|
|
16717
16859
|
])
|
|
16718
16860
|
] : [],
|
|
@@ -16752,7 +16894,7 @@ var init_loadSimpleCapability = __esm({
|
|
|
16752
16894
|
});
|
|
16753
16895
|
|
|
16754
16896
|
// src/taskContext.ts
|
|
16755
|
-
import * as
|
|
16897
|
+
import * as fs47 from "fs";
|
|
16756
16898
|
import * as path44 from "path";
|
|
16757
16899
|
function buildTaskContext(args) {
|
|
16758
16900
|
return {
|
|
@@ -16769,9 +16911,9 @@ function buildTaskContext(args) {
|
|
|
16769
16911
|
function persistTaskContext(cwd, ctx) {
|
|
16770
16912
|
try {
|
|
16771
16913
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
16772
|
-
|
|
16914
|
+
fs47.mkdirSync(dir, { recursive: true });
|
|
16773
16915
|
const file = path44.join(dir, "task-context.json");
|
|
16774
|
-
|
|
16916
|
+
fs47.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
16775
16917
|
`);
|
|
16776
16918
|
return file;
|
|
16777
16919
|
} catch (err) {
|
|
@@ -17692,7 +17834,7 @@ var init_parseReproOutput = __esm({
|
|
|
17692
17834
|
});
|
|
17693
17835
|
|
|
17694
17836
|
// src/scripts/parseSimpleCapabilityOutput.ts
|
|
17695
|
-
import * as
|
|
17837
|
+
import * as fs48 from "fs";
|
|
17696
17838
|
function acceptAuthoritativeCapabilityOutput(ctx, profile, output) {
|
|
17697
17839
|
ctx.data.agentDone = true;
|
|
17698
17840
|
delete ctx.data.agentFailureReason;
|
|
@@ -17709,11 +17851,11 @@ function stringList2(value) {
|
|
|
17709
17851
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
17710
17852
|
}
|
|
17711
17853
|
function readOutputFile(outputPath) {
|
|
17712
|
-
if (!outputPath || !
|
|
17854
|
+
if (!outputPath || !fs48.existsSync(outputPath)) return { found: false };
|
|
17713
17855
|
try {
|
|
17714
|
-
return { found: true, value: JSON.parse(
|
|
17856
|
+
return { found: true, value: JSON.parse(fs48.readFileSync(outputPath, "utf-8")) };
|
|
17715
17857
|
} finally {
|
|
17716
|
-
|
|
17858
|
+
fs48.rmSync(outputPath, { force: true });
|
|
17717
17859
|
}
|
|
17718
17860
|
}
|
|
17719
17861
|
function parseOutput(text2) {
|
|
@@ -18335,7 +18477,7 @@ var init_postResearchComment = __esm({
|
|
|
18335
18477
|
});
|
|
18336
18478
|
|
|
18337
18479
|
// src/scripts/prepareBrowserAuth.ts
|
|
18338
|
-
import * as
|
|
18480
|
+
import * as fs49 from "fs";
|
|
18339
18481
|
import * as os7 from "os";
|
|
18340
18482
|
import * as path45 from "path";
|
|
18341
18483
|
function appendAuthMessage(ctx, message) {
|
|
@@ -18381,8 +18523,8 @@ async function githubJson(url, token, checkName) {
|
|
|
18381
18523
|
throw new Error(`GitHub ${checkName} check failed`);
|
|
18382
18524
|
}
|
|
18383
18525
|
function writeKodyStorageState(input) {
|
|
18384
|
-
const directory =
|
|
18385
|
-
|
|
18526
|
+
const directory = fs49.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
|
|
18527
|
+
fs49.chmodSync(directory, 448);
|
|
18386
18528
|
const file = path45.join(directory, "storage-state.json");
|
|
18387
18529
|
const now = Date.now();
|
|
18388
18530
|
const repoEntry = {
|
|
@@ -18414,7 +18556,7 @@ function writeKodyStorageState(input) {
|
|
|
18414
18556
|
}
|
|
18415
18557
|
]
|
|
18416
18558
|
};
|
|
18417
|
-
|
|
18559
|
+
fs49.writeFileSync(file, JSON.stringify(storageState), { mode: 384 });
|
|
18418
18560
|
return { directory, file, auth };
|
|
18419
18561
|
}
|
|
18420
18562
|
function parseSetCookie(value, hostname) {
|
|
@@ -18444,10 +18586,10 @@ function parseSetCookie(value, hostname) {
|
|
|
18444
18586
|
}
|
|
18445
18587
|
function writeCookieStorageState(targetUrl, setCookies) {
|
|
18446
18588
|
const target = new URL(targetUrl);
|
|
18447
|
-
const directory =
|
|
18448
|
-
|
|
18589
|
+
const directory = fs49.mkdtempSync(path45.join(os7.tmpdir(), "kody-browser-auth-"));
|
|
18590
|
+
fs49.chmodSync(directory, 448);
|
|
18449
18591
|
const file = path45.join(directory, "storage-state.json");
|
|
18450
|
-
|
|
18592
|
+
fs49.writeFileSync(
|
|
18451
18593
|
file,
|
|
18452
18594
|
JSON.stringify({
|
|
18453
18595
|
cookies: setCookies.map((cookie) => parseSetCookie(cookie, target.hostname)),
|
|
@@ -18468,9 +18610,9 @@ function currentStorageStatePath(args) {
|
|
|
18468
18610
|
function browserSessionCookieHeader(profile, targetUrl) {
|
|
18469
18611
|
const playwright = profile.claudeCode.mcpServers.find((server) => server.name === "playwright");
|
|
18470
18612
|
const storagePath = currentStorageStatePath(playwright?.args ?? []);
|
|
18471
|
-
if (!storagePath || !
|
|
18613
|
+
if (!storagePath || !fs49.existsSync(storagePath)) return void 0;
|
|
18472
18614
|
const hostname = new URL(targetUrl).hostname;
|
|
18473
|
-
const state = JSON.parse(
|
|
18615
|
+
const state = JSON.parse(fs49.readFileSync(storagePath, "utf-8"));
|
|
18474
18616
|
const cookies = (state.cookies ?? []).filter((cookie) => {
|
|
18475
18617
|
const domain = cookie.domain.replace(/^\./, "");
|
|
18476
18618
|
return hostname === domain || hostname.endsWith(`.${domain}`);
|
|
@@ -18517,10 +18659,29 @@ async function prepareAccountCredentials(ctx, profile, input) {
|
|
|
18517
18659
|
appendAuthMessage(ctx, "Auth: the QA account's required model credentials are already prepared by the engine.");
|
|
18518
18660
|
return true;
|
|
18519
18661
|
}
|
|
18662
|
+
async function prepareAccountModelSettings(ctx, profile, input) {
|
|
18663
|
+
const cookie = browserSessionCookieHeader(profile, input.targetUrl);
|
|
18664
|
+
if (!cookie) {
|
|
18665
|
+
appendAuthMessage(ctx, "Auth: QA Chat model setup could not run because the app session is missing.");
|
|
18666
|
+
return false;
|
|
18667
|
+
}
|
|
18668
|
+
const origin = browserOrigin(input.targetUrl);
|
|
18669
|
+
const response = await fetch(`${origin}/api/kody/models`, {
|
|
18670
|
+
method: "PUT",
|
|
18671
|
+
headers: { "content-type": "application/json", cookie, origin },
|
|
18672
|
+
body: JSON.stringify(input.settings)
|
|
18673
|
+
});
|
|
18674
|
+
if (!response.ok) {
|
|
18675
|
+
appendAuthMessage(ctx, `Auth: QA Chat model setup returned ${response.status}.`);
|
|
18676
|
+
return false;
|
|
18677
|
+
}
|
|
18678
|
+
appendAuthMessage(ctx, "Auth: the QA account's Chat model is already prepared by the engine.");
|
|
18679
|
+
return true;
|
|
18680
|
+
}
|
|
18520
18681
|
function mergeStorageStates(existingPath, nextPath) {
|
|
18521
|
-
if (existingPath === nextPath || !
|
|
18522
|
-
const existing = JSON.parse(
|
|
18523
|
-
const next = JSON.parse(
|
|
18682
|
+
if (existingPath === nextPath || !fs49.existsSync(existingPath)) return;
|
|
18683
|
+
const existing = JSON.parse(fs49.readFileSync(existingPath, "utf-8"));
|
|
18684
|
+
const next = JSON.parse(fs49.readFileSync(nextPath, "utf-8"));
|
|
18524
18685
|
const cookies = /* @__PURE__ */ new Map();
|
|
18525
18686
|
for (const cookie of [...existing.cookies ?? [], ...next.cookies ?? []]) {
|
|
18526
18687
|
cookies.set(`${cookie.name}\0${cookie.domain}\0${cookie.path}`, cookie);
|
|
@@ -18534,7 +18695,7 @@ function mergeStorageStates(existingPath, nextPath) {
|
|
|
18534
18695
|
}
|
|
18535
18696
|
origins.set(entry.origin, { origin: entry.origin, localStorage: [...localStorage.values()] });
|
|
18536
18697
|
}
|
|
18537
|
-
|
|
18698
|
+
fs49.writeFileSync(
|
|
18538
18699
|
nextPath,
|
|
18539
18700
|
JSON.stringify({ cookies: [...cookies.values()], origins: [...origins.values()] }),
|
|
18540
18701
|
{ mode: 384 }
|
|
@@ -18631,7 +18792,7 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
|
|
|
18631
18792
|
configurePlaywright(profile, state.file);
|
|
18632
18793
|
const authDirectory = state.directory;
|
|
18633
18794
|
registerRuntimeCleanup(ctx, () => {
|
|
18634
|
-
|
|
18795
|
+
fs49.rmSync(authDirectory, { recursive: true, force: true });
|
|
18635
18796
|
});
|
|
18636
18797
|
appendAuthMessage(
|
|
18637
18798
|
ctx,
|
|
@@ -18639,7 +18800,7 @@ async function prepareKodyRepositoryBrowserAuth(ctx, profile, input) {
|
|
|
18639
18800
|
);
|
|
18640
18801
|
return true;
|
|
18641
18802
|
} catch (error) {
|
|
18642
|
-
if (state)
|
|
18803
|
+
if (state) fs49.rmSync(state.directory, { recursive: true, force: true });
|
|
18643
18804
|
const reason = error instanceof Error ? error.message : String(error);
|
|
18644
18805
|
appendAuthMessage(
|
|
18645
18806
|
ctx,
|
|
@@ -18666,11 +18827,11 @@ async function prepareEmailPasswordBrowserAuth(ctx, profile, input) {
|
|
|
18666
18827
|
state = writeCookieStorageState(input.targetUrl, cookies);
|
|
18667
18828
|
configurePlaywright(profile, state.file);
|
|
18668
18829
|
const authDirectory = state.directory;
|
|
18669
|
-
registerRuntimeCleanup(ctx, () =>
|
|
18830
|
+
registerRuntimeCleanup(ctx, () => fs49.rmSync(authDirectory, { recursive: true, force: true }));
|
|
18670
18831
|
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.";
|
|
18671
18832
|
return true;
|
|
18672
18833
|
} catch (error) {
|
|
18673
|
-
if (state)
|
|
18834
|
+
if (state) fs49.rmSync(state.directory, { recursive: true, force: true });
|
|
18674
18835
|
const reason = error instanceof Error ? error.message : String(error);
|
|
18675
18836
|
ctx.data.qaAuthBlock = `Auth: the engine could not prepare the app login (${reason}). Note this authenticated surface as a gap.`;
|
|
18676
18837
|
return false;
|
|
@@ -18914,6 +19075,12 @@ var init_prepareSimpleCapabilityRuntime = __esm({
|
|
|
18914
19075
|
targetUrl
|
|
18915
19076
|
});
|
|
18916
19077
|
}
|
|
19078
|
+
if (requirements.qaAccountModelSettings) {
|
|
19079
|
+
await prepareAccountModelSettings(ctx, profile, {
|
|
19080
|
+
settings: requirements.qaAccountModelSettings,
|
|
19081
|
+
targetUrl
|
|
19082
|
+
});
|
|
19083
|
+
}
|
|
18917
19084
|
}
|
|
18918
19085
|
if (requirements.githubTestToken) {
|
|
18919
19086
|
const capabilityInput = ctx.data.capabilityInput && typeof ctx.data.capabilityInput === "object" && !Array.isArray(ctx.data.capabilityInput) ? ctx.data.capabilityInput : {};
|
|
@@ -20578,7 +20745,7 @@ var init_tickShellRunner = __esm({
|
|
|
20578
20745
|
});
|
|
20579
20746
|
|
|
20580
20747
|
// src/scripts/runScheduledImplementationTick.ts
|
|
20581
|
-
import * as
|
|
20748
|
+
import * as fs50 from "fs";
|
|
20582
20749
|
import * as path48 from "path";
|
|
20583
20750
|
var runScheduledImplementationTick;
|
|
20584
20751
|
var init_runScheduledImplementationTick = __esm({
|
|
@@ -20607,7 +20774,7 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
20607
20774
|
return;
|
|
20608
20775
|
}
|
|
20609
20776
|
const shellPath = path48.join(profile.dir, shell);
|
|
20610
|
-
if (!
|
|
20777
|
+
if (!fs50.existsSync(shellPath)) {
|
|
20611
20778
|
ctx.output.exitCode = 99;
|
|
20612
20779
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
20613
20780
|
return;
|
|
@@ -20639,13 +20806,13 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
20639
20806
|
|
|
20640
20807
|
// src/scripts/runSimpleCapabilityScript.ts
|
|
20641
20808
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
20642
|
-
import * as
|
|
20809
|
+
import * as fs51 from "fs";
|
|
20643
20810
|
function formatDuration2(timeoutMs) {
|
|
20644
20811
|
return timeoutMs % 6e4 === 0 ? `${timeoutMs / 6e4} minutes` : `${timeoutMs}ms`;
|
|
20645
20812
|
}
|
|
20646
20813
|
function isRegularFile2(filePath) {
|
|
20647
20814
|
try {
|
|
20648
|
-
const stat =
|
|
20815
|
+
const stat = fs51.lstatSync(filePath);
|
|
20649
20816
|
return stat.isFile() && !stat.isSymbolicLink();
|
|
20650
20817
|
} catch {
|
|
20651
20818
|
return false;
|
|
@@ -20724,7 +20891,7 @@ var init_runSimpleCapabilityScript = __esm({
|
|
|
20724
20891
|
});
|
|
20725
20892
|
|
|
20726
20893
|
// src/scripts/runTickScript.ts
|
|
20727
|
-
import * as
|
|
20894
|
+
import * as fs52 from "fs";
|
|
20728
20895
|
import * as path49 from "path";
|
|
20729
20896
|
var runTickScript;
|
|
20730
20897
|
var init_runTickScript = __esm({
|
|
@@ -20758,7 +20925,7 @@ var init_runTickScript = __esm({
|
|
|
20758
20925
|
return;
|
|
20759
20926
|
}
|
|
20760
20927
|
const scriptPath = path49.isAbsolute(tickScript) ? tickScript : path49.join(ctx.cwd, tickScript);
|
|
20761
|
-
if (!
|
|
20928
|
+
if (!fs52.existsSync(scriptPath)) {
|
|
20762
20929
|
ctx.output.exitCode = 99;
|
|
20763
20930
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
20764
20931
|
return;
|
|
@@ -20806,6 +20973,41 @@ var init_saveManagedGoalState = __esm({
|
|
|
20806
20973
|
}
|
|
20807
20974
|
});
|
|
20808
20975
|
|
|
20976
|
+
// src/scripts/saveLiveAgentState.ts
|
|
20977
|
+
var saveLiveAgentState;
|
|
20978
|
+
var init_saveLiveAgentState = __esm({
|
|
20979
|
+
"src/scripts/saveLiveAgentState.ts"() {
|
|
20980
|
+
"use strict";
|
|
20981
|
+
init_state_backend();
|
|
20982
|
+
saveLiveAgentState = async (ctx, _profile, agentResult) => {
|
|
20983
|
+
const agent = String(ctx.data.liveAgentSlug ?? "");
|
|
20984
|
+
const previousRevision = Number(ctx.data.liveAgentPreviousRevision ?? 0);
|
|
20985
|
+
const next = ctx.data.nextJobState;
|
|
20986
|
+
if (!agent || !next || typeof next.cursor !== "string" || !next.cursor) {
|
|
20987
|
+
throw new Error(String(ctx.data.nextStateParseError ?? "Live Agent did not submit valid continuation state"));
|
|
20988
|
+
}
|
|
20989
|
+
const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY ?? "").split("/");
|
|
20990
|
+
const owner = ctx.config.github?.owner?.trim() || envOwner;
|
|
20991
|
+
const repo = ctx.config.github?.repo?.trim() || envRepo;
|
|
20992
|
+
if (!owner || !repo) throw new Error("Repository identity is required for live Agent state");
|
|
20993
|
+
const summary = (agentResult?.finalText ?? "").trim().slice(0, 1e3);
|
|
20994
|
+
await createStateBackendFromEnv().saveAgentState(
|
|
20995
|
+
`${owner}/${repo}`,
|
|
20996
|
+
{
|
|
20997
|
+
version: 1,
|
|
20998
|
+
agent,
|
|
20999
|
+
revision: previousRevision + 1,
|
|
21000
|
+
cursor: next.cursor,
|
|
21001
|
+
summary,
|
|
21002
|
+
data: next.data && typeof next.data === "object" ? next.data : {},
|
|
21003
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21004
|
+
},
|
|
21005
|
+
previousRevision
|
|
21006
|
+
);
|
|
21007
|
+
};
|
|
21008
|
+
}
|
|
21009
|
+
});
|
|
21010
|
+
|
|
20809
21011
|
// src/scripts/setCommentTarget.ts
|
|
20810
21012
|
var setCommentTarget;
|
|
20811
21013
|
var init_setCommentTarget = __esm({
|
|
@@ -21923,7 +22125,7 @@ var init_warmupMcp = __esm({
|
|
|
21923
22125
|
});
|
|
21924
22126
|
|
|
21925
22127
|
// src/scripts/writeAgentRunSummary.ts
|
|
21926
|
-
import * as
|
|
22128
|
+
import * as fs53 from "fs";
|
|
21927
22129
|
var writeAgentRunSummary;
|
|
21928
22130
|
var init_writeAgentRunSummary = __esm({
|
|
21929
22131
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -21949,7 +22151,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
21949
22151
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
21950
22152
|
lines.push("");
|
|
21951
22153
|
try {
|
|
21952
|
-
|
|
22154
|
+
fs53.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
21953
22155
|
`);
|
|
21954
22156
|
} catch {
|
|
21955
22157
|
}
|
|
@@ -22106,6 +22308,7 @@ var init_scripts = __esm({
|
|
|
22106
22308
|
init_loadIssueStateComment();
|
|
22107
22309
|
init_loadJobFromFile();
|
|
22108
22310
|
init_loadLinkedFinding();
|
|
22311
|
+
init_loadLiveAgent();
|
|
22109
22312
|
init_loadMemoryContext();
|
|
22110
22313
|
init_loadPriorArt();
|
|
22111
22314
|
init_loadQaContext();
|
|
@@ -22154,6 +22357,7 @@ var init_scripts = __esm({
|
|
|
22154
22357
|
init_runSimpleCapabilityScript();
|
|
22155
22358
|
init_runTickScript();
|
|
22156
22359
|
init_saveManagedGoalState();
|
|
22360
|
+
init_saveLiveAgentState();
|
|
22157
22361
|
init_saveTaskState();
|
|
22158
22362
|
init_setCommentTarget();
|
|
22159
22363
|
init_setLifecycleLabel();
|
|
@@ -22193,6 +22397,7 @@ var init_scripts = __esm({
|
|
|
22193
22397
|
loadConventions,
|
|
22194
22398
|
loadCoverageRules,
|
|
22195
22399
|
loadLinkedFinding,
|
|
22400
|
+
loadLiveAgent,
|
|
22196
22401
|
loadMemoryContext,
|
|
22197
22402
|
loadPriorArt,
|
|
22198
22403
|
loadQaContext,
|
|
@@ -22228,6 +22433,7 @@ var init_scripts = __esm({
|
|
|
22228
22433
|
saveManagedGoalState
|
|
22229
22434
|
};
|
|
22230
22435
|
postflightScripts = {
|
|
22436
|
+
saveLiveAgentState,
|
|
22231
22437
|
parseSimpleCapabilityOutput,
|
|
22232
22438
|
parseAgentResult: parseAgentResult2,
|
|
22233
22439
|
parseIssueStateFromAgentResult,
|
|
@@ -22287,7 +22493,7 @@ var init_scripts = __esm({
|
|
|
22287
22493
|
});
|
|
22288
22494
|
|
|
22289
22495
|
// src/stateWorkspace.ts
|
|
22290
|
-
import * as
|
|
22496
|
+
import * as fs54 from "fs";
|
|
22291
22497
|
import * as path51 from "path";
|
|
22292
22498
|
function tenantId(config) {
|
|
22293
22499
|
const owner = config.github?.owner?.trim() || process.env.GITHUB_REPOSITORY?.split("/")[0]?.trim();
|
|
@@ -22296,8 +22502,8 @@ function tenantId(config) {
|
|
|
22296
22502
|
}
|
|
22297
22503
|
function writeRuntimeFile(cwd, relativePath, content) {
|
|
22298
22504
|
const target = path51.join(cwd, RUNTIME_ROOT, relativePath);
|
|
22299
|
-
|
|
22300
|
-
|
|
22505
|
+
fs54.mkdirSync(path51.dirname(target), { recursive: true });
|
|
22506
|
+
fs54.writeFileSync(target, content, "utf8");
|
|
22301
22507
|
}
|
|
22302
22508
|
function record(value) {
|
|
22303
22509
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -22318,8 +22524,8 @@ function memoryIndex(docs) {
|
|
|
22318
22524
|
if (lines.length === 0) return "";
|
|
22319
22525
|
return ["# Kody memory index", "", "One line per backend memory document.", "", ...lines, ""].join("\n");
|
|
22320
22526
|
}
|
|
22321
|
-
async function hydratePrefix(backend,
|
|
22322
|
-
const docs = await backend.listRepoDocs(
|
|
22527
|
+
async function hydratePrefix(backend, tenant2, cwd, prefix) {
|
|
22528
|
+
const docs = await backend.listRepoDocs(tenant2, prefix);
|
|
22323
22529
|
for (const doc of docs) {
|
|
22324
22530
|
const slug = doc.kind.slice(prefix.length);
|
|
22325
22531
|
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(slug)) continue;
|
|
@@ -22332,8 +22538,8 @@ async function hydratePrefix(backend, tenant, cwd, prefix) {
|
|
|
22332
22538
|
if (index) writeRuntimeFile(cwd, "memory/INDEX.md", index);
|
|
22333
22539
|
}
|
|
22334
22540
|
}
|
|
22335
|
-
async function hydrateSingleton(backend,
|
|
22336
|
-
const doc = await backend.getRepoDoc(
|
|
22541
|
+
async function hydrateSingleton(backend, tenant2, cwd, kind, relativePath) {
|
|
22542
|
+
const doc = await backend.getRepoDoc(tenant2, kind);
|
|
22337
22543
|
if (!doc) return;
|
|
22338
22544
|
const body = stringField6(doc.doc, "body");
|
|
22339
22545
|
if (body !== null) {
|
|
@@ -22343,8 +22549,8 @@ async function hydrateSingleton(backend, tenant, cwd, kind, relativePath) {
|
|
|
22343
22549
|
writeRuntimeFile(cwd, relativePath, `${JSON.stringify(doc.doc, null, 2)}
|
|
22344
22550
|
`);
|
|
22345
22551
|
}
|
|
22346
|
-
async function hydrateWorkflows(backend,
|
|
22347
|
-
for (const workflow of await backend.listWorkflows(
|
|
22552
|
+
async function hydrateWorkflows(backend, tenant2, cwd) {
|
|
22553
|
+
for (const workflow of await backend.listWorkflows(tenant2)) {
|
|
22348
22554
|
if (!/^[a-z0-9][a-z0-9_-]{0,79}$/.test(workflow.workflowId)) continue;
|
|
22349
22555
|
writeRuntimeFile(
|
|
22350
22556
|
cwd,
|
|
@@ -22355,25 +22561,25 @@ async function hydrateWorkflows(backend, tenant, cwd) {
|
|
|
22355
22561
|
}
|
|
22356
22562
|
}
|
|
22357
22563
|
async function hydrateStateWorkspace(config, cwd, backendOverride) {
|
|
22358
|
-
const
|
|
22564
|
+
const tenant2 = tenantId(config);
|
|
22359
22565
|
const configured = hasStateBackendConfig();
|
|
22360
|
-
if (!
|
|
22566
|
+
if (!tenant2 || !configured) {
|
|
22361
22567
|
if (process.env.GITHUB_ACTIONS === "true")
|
|
22362
22568
|
throw new Error("Kody backend access is required for runtime workspace documents");
|
|
22363
22569
|
return;
|
|
22364
22570
|
}
|
|
22365
|
-
const key = `${path51.resolve(cwd)}|${
|
|
22571
|
+
const key = `${path51.resolve(cwd)}|${tenant2}`;
|
|
22366
22572
|
if (hydratedWorkspaces.has(key)) return;
|
|
22367
22573
|
const backend = backendOverride ?? createStateBackendFromEnv();
|
|
22368
22574
|
const root = path51.join(cwd, RUNTIME_ROOT);
|
|
22369
|
-
|
|
22575
|
+
fs54.rmSync(root, { recursive: true, force: true });
|
|
22370
22576
|
await Promise.all([
|
|
22371
|
-
hydratePrefix(backend,
|
|
22372
|
-
hydratePrefix(backend,
|
|
22373
|
-
hydrateSingleton(backend,
|
|
22374
|
-
hydrateSingleton(backend,
|
|
22375
|
-
hydrateSingleton(backend,
|
|
22376
|
-
hydrateWorkflows(backend,
|
|
22577
|
+
hydratePrefix(backend, tenant2, cwd, "context:"),
|
|
22578
|
+
hydratePrefix(backend, tenant2, cwd, "memory:"),
|
|
22579
|
+
hydrateSingleton(backend, tenant2, cwd, "instructions", "instructions.md"),
|
|
22580
|
+
hydrateSingleton(backend, tenant2, cwd, "system-prompt", "system-prompt.md"),
|
|
22581
|
+
hydrateSingleton(backend, tenant2, cwd, "variables", "variables.json"),
|
|
22582
|
+
hydrateWorkflows(backend, tenant2, cwd)
|
|
22377
22583
|
]);
|
|
22378
22584
|
hydratedWorkspaces.add(key);
|
|
22379
22585
|
}
|
|
@@ -22453,7 +22659,7 @@ var init_tools = __esm({
|
|
|
22453
22659
|
|
|
22454
22660
|
// src/executor.ts
|
|
22455
22661
|
import { spawn as spawn8 } from "child_process";
|
|
22456
|
-
import * as
|
|
22662
|
+
import * as fs55 from "fs";
|
|
22457
22663
|
import * as os8 from "os";
|
|
22458
22664
|
import * as path52 from "path";
|
|
22459
22665
|
function isMutatingPostflight(scriptName) {
|
|
@@ -23240,7 +23446,7 @@ function resolveProfilePath(profileName, cwd = process.cwd()) {
|
|
|
23240
23446
|
// fallback
|
|
23241
23447
|
];
|
|
23242
23448
|
for (const c of candidates) {
|
|
23243
|
-
if (
|
|
23449
|
+
if (fs55.existsSync(c)) return c;
|
|
23244
23450
|
}
|
|
23245
23451
|
return candidates[0];
|
|
23246
23452
|
}
|
|
@@ -23356,7 +23562,7 @@ function resolveShellTimeoutMs(entry) {
|
|
|
23356
23562
|
async function runShellEntry(entry, ctx, profile) {
|
|
23357
23563
|
const shellName = entry.shell;
|
|
23358
23564
|
const shellPath = path52.join(profile.dir, shellName);
|
|
23359
|
-
if (!
|
|
23565
|
+
if (!fs55.existsSync(shellPath)) {
|
|
23360
23566
|
ctx.skipAgent = true;
|
|
23361
23567
|
ctx.output.exitCode = 99;
|
|
23362
23568
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -23430,9 +23636,9 @@ async function runShellEntry(entry, ctx, profile) {
|
|
|
23430
23636
|
}
|
|
23431
23637
|
let sideChannelText = "";
|
|
23432
23638
|
try {
|
|
23433
|
-
if (
|
|
23434
|
-
sideChannelText =
|
|
23435
|
-
|
|
23639
|
+
if (fs55.existsSync(outputFile)) {
|
|
23640
|
+
sideChannelText = fs55.readFileSync(outputFile, "utf-8");
|
|
23641
|
+
fs55.rmSync(outputFile, { force: true });
|
|
23436
23642
|
}
|
|
23437
23643
|
} catch {
|
|
23438
23644
|
}
|
|
@@ -26165,7 +26371,7 @@ async function hydrateDefinitionsFromEnv(cwd = process.cwd(), env = process.env)
|
|
|
26165
26371
|
|
|
26166
26372
|
// src/kody-cli.ts
|
|
26167
26373
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
26168
|
-
import * as
|
|
26374
|
+
import * as fs56 from "fs";
|
|
26169
26375
|
import * as path53 from "path";
|
|
26170
26376
|
|
|
26171
26377
|
// src/app-auth.ts
|
|
@@ -26213,26 +26419,6 @@ async function ghApp(jwt, apiPath, method = "GET") {
|
|
|
26213
26419
|
}
|
|
26214
26420
|
return await res.json();
|
|
26215
26421
|
}
|
|
26216
|
-
async function ghAppPage(authToken, apiPath) {
|
|
26217
|
-
const res = await fetch(`${GH_API}${apiPath}`, {
|
|
26218
|
-
headers: {
|
|
26219
|
-
Authorization: `Bearer ${authToken}`,
|
|
26220
|
-
Accept: "application/vnd.github+json",
|
|
26221
|
-
"X-GitHub-Api-Version": "2022-11-28",
|
|
26222
|
-
"User-Agent": "kody-engine"
|
|
26223
|
-
}
|
|
26224
|
-
});
|
|
26225
|
-
if (!res.ok) {
|
|
26226
|
-
const body = await res.text().catch(() => "");
|
|
26227
|
-
throw new Error(
|
|
26228
|
-
`GitHub App API GET ${apiPath} \u2192 ${res.status} ${res.statusText}${body ? `: ${body.slice(0, 200)}` : ""}`
|
|
26229
|
-
);
|
|
26230
|
-
}
|
|
26231
|
-
return {
|
|
26232
|
-
data: await res.json(),
|
|
26233
|
-
hasNext: /rel="next"/.test(res.headers.get("link") ?? "")
|
|
26234
|
-
};
|
|
26235
|
-
}
|
|
26236
26422
|
function readAppCreds(env = process.env) {
|
|
26237
26423
|
const appId = env.KODY_APP_ID?.trim();
|
|
26238
26424
|
const privateKey = env.KODY_APP_PRIVATE_KEY;
|
|
@@ -26257,36 +26443,6 @@ async function mintAppInstallationToken(creds) {
|
|
|
26257
26443
|
const tok = await ghApp(jwt, `/app/installations/${installationId}/access_tokens`, "POST");
|
|
26258
26444
|
return tok.token;
|
|
26259
26445
|
}
|
|
26260
|
-
async function discoverAppRepositories(creds) {
|
|
26261
|
-
const jwt = buildAppJwt(creds.appId, creds.privateKey);
|
|
26262
|
-
const installations = [];
|
|
26263
|
-
for (let page = 1; ; page++) {
|
|
26264
|
-
const result = await ghAppPage(jwt, `/app/installations?per_page=100&page=${page}`);
|
|
26265
|
-
installations.push(...result.data.filter((item) => Number.isInteger(item.id) && item.id > 0));
|
|
26266
|
-
if (!result.hasNext) break;
|
|
26267
|
-
}
|
|
26268
|
-
const byRepo = /* @__PURE__ */ new Map();
|
|
26269
|
-
for (const installation of installations) {
|
|
26270
|
-
const token = await mintAppInstallationToken({
|
|
26271
|
-
appId: creds.appId,
|
|
26272
|
-
privateKey: creds.privateKey,
|
|
26273
|
-
installationId: String(installation.id)
|
|
26274
|
-
});
|
|
26275
|
-
for (let page = 1; ; page++) {
|
|
26276
|
-
const result = await ghAppPage(
|
|
26277
|
-
token,
|
|
26278
|
-
`/installation/repositories?per_page=100&page=${page}`
|
|
26279
|
-
);
|
|
26280
|
-
for (const repository of result.data.repositories ?? []) {
|
|
26281
|
-
const repo = repository.full_name?.trim();
|
|
26282
|
-
if (!repo || !/^[^/\s]+\/[^/\s]+$/.test(repo)) continue;
|
|
26283
|
-
byRepo.set(repo.toLowerCase(), { repo, token });
|
|
26284
|
-
}
|
|
26285
|
-
if (!result.hasNext) break;
|
|
26286
|
-
}
|
|
26287
|
-
}
|
|
26288
|
-
return [...byRepo.values()].sort((left, right) => left.repo.localeCompare(right.repo));
|
|
26289
|
-
}
|
|
26290
26446
|
|
|
26291
26447
|
// src/kody-cli.ts
|
|
26292
26448
|
init_capabilityFolders();
|
|
@@ -26968,9 +27124,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
26968
27124
|
return void 0;
|
|
26969
27125
|
}
|
|
26970
27126
|
function detectPackageManager2(cwd) {
|
|
26971
|
-
if (
|
|
26972
|
-
if (
|
|
26973
|
-
if (
|
|
27127
|
+
if (fs56.existsSync(path53.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
27128
|
+
if (fs56.existsSync(path53.join(cwd, "yarn.lock"))) return "yarn";
|
|
27129
|
+
if (fs56.existsSync(path53.join(cwd, "bun.lockb"))) return "bun";
|
|
26974
27130
|
return "npm";
|
|
26975
27131
|
}
|
|
26976
27132
|
function shouldChainScheduledWatch(match) {
|
|
@@ -27073,8 +27229,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
27073
27229
|
const logPath = lastRunLogPath(cwd);
|
|
27074
27230
|
let tail = "";
|
|
27075
27231
|
try {
|
|
27076
|
-
if (
|
|
27077
|
-
const content =
|
|
27232
|
+
if (fs56.existsSync(logPath)) {
|
|
27233
|
+
const content = fs56.readFileSync(logPath, "utf-8");
|
|
27078
27234
|
tail = content.slice(-3e3);
|
|
27079
27235
|
}
|
|
27080
27236
|
} catch {
|
|
@@ -27169,9 +27325,9 @@ async function runCi(argv) {
|
|
|
27169
27325
|
forceRunCliArgs = { goal: envForceMessage };
|
|
27170
27326
|
}
|
|
27171
27327
|
}
|
|
27172
|
-
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
27328
|
+
if (!args.issueNumber && !autoFallback && !forceRunAction && !runRequestFanOut && eventName === "workflow_dispatch" && dispatchEventPath && fs56.existsSync(dispatchEventPath)) {
|
|
27173
27329
|
try {
|
|
27174
|
-
const evt = JSON.parse(
|
|
27330
|
+
const evt = JSON.parse(fs56.readFileSync(dispatchEventPath, "utf-8"));
|
|
27175
27331
|
const inputs = objectValue2(evt.inputs);
|
|
27176
27332
|
const issueInput = parseInt(String(inputs?.issue_number ?? ""), 10);
|
|
27177
27333
|
const sessionInput = String(inputs?.sessionId ?? "");
|
|
@@ -27586,7 +27742,7 @@ init_repoWorkspace();
|
|
|
27586
27742
|
|
|
27587
27743
|
// src/scripts/brainTurnLog.ts
|
|
27588
27744
|
init_runtimePaths();
|
|
27589
|
-
import * as
|
|
27745
|
+
import * as fs57 from "fs";
|
|
27590
27746
|
import * as path54 from "path";
|
|
27591
27747
|
import posixPath4 from "path/posix";
|
|
27592
27748
|
var live = /* @__PURE__ */ new Map();
|
|
@@ -27595,8 +27751,8 @@ function brainEventsFilePath(dir, chatId) {
|
|
|
27595
27751
|
}
|
|
27596
27752
|
function lastPersistedSeq(dir, chatId) {
|
|
27597
27753
|
const p = brainEventsFilePath(dir, chatId);
|
|
27598
|
-
if (!
|
|
27599
|
-
const lines =
|
|
27754
|
+
if (!fs57.existsSync(p)) return 0;
|
|
27755
|
+
const lines = fs57.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
27600
27756
|
if (lines.length === 0) return 0;
|
|
27601
27757
|
try {
|
|
27602
27758
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -27606,9 +27762,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
27606
27762
|
}
|
|
27607
27763
|
function readSince(dir, chatId, since) {
|
|
27608
27764
|
const p = brainEventsFilePath(dir, chatId);
|
|
27609
|
-
if (!
|
|
27765
|
+
if (!fs57.existsSync(p)) return [];
|
|
27610
27766
|
const out = [];
|
|
27611
|
-
for (const line of
|
|
27767
|
+
for (const line of fs57.readFileSync(p, "utf-8").split("\n")) {
|
|
27612
27768
|
if (!line) continue;
|
|
27613
27769
|
try {
|
|
27614
27770
|
const rec = JSON.parse(line);
|
|
@@ -27634,12 +27790,12 @@ function beginTurn(dir, chatId) {
|
|
|
27634
27790
|
};
|
|
27635
27791
|
live.set(chatId, state);
|
|
27636
27792
|
const p = brainEventsFilePath(dir, chatId);
|
|
27637
|
-
|
|
27793
|
+
fs57.mkdirSync(path54.dirname(p), { recursive: true });
|
|
27638
27794
|
return (event) => {
|
|
27639
27795
|
state.seq += 1;
|
|
27640
27796
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
27641
27797
|
try {
|
|
27642
|
-
|
|
27798
|
+
fs57.appendFileSync(p, `${JSON.stringify(rec)}
|
|
27643
27799
|
`);
|
|
27644
27800
|
} catch (err) {
|
|
27645
27801
|
process.stderr.write(
|
|
@@ -27678,7 +27834,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
27678
27834
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
27679
27835
|
};
|
|
27680
27836
|
try {
|
|
27681
|
-
|
|
27837
|
+
fs57.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
27682
27838
|
`);
|
|
27683
27839
|
} catch {
|
|
27684
27840
|
}
|
|
@@ -29665,55 +29821,6 @@ async function brainTerminalAgent(options) {
|
|
|
29665
29821
|
|
|
29666
29822
|
// src/servers/pool-serve.ts
|
|
29667
29823
|
import { createServer as createServer5 } from "http";
|
|
29668
|
-
|
|
29669
|
-
// src/pool/agency-loop-tick.ts
|
|
29670
|
-
function normalizeRepositories(repositories) {
|
|
29671
|
-
const unique = /* @__PURE__ */ new Set();
|
|
29672
|
-
for (const raw of repositories) {
|
|
29673
|
-
const repo = raw.trim().toLowerCase();
|
|
29674
|
-
if (/^[^/\s]+\/[^/\s]+$/.test(repo)) unique.add(repo);
|
|
29675
|
-
}
|
|
29676
|
-
return [...unique].sort();
|
|
29677
|
-
}
|
|
29678
|
-
async function runAgencyLoopTick(deps) {
|
|
29679
|
-
const repositories = normalizeRepositories(await deps.discover());
|
|
29680
|
-
if (repositories.length === 0) {
|
|
29681
|
-
deps.log("no consumer agencies discovered \u2014 nothing to tick");
|
|
29682
|
-
return { discovered: 0, claimed: 0 };
|
|
29683
|
-
}
|
|
29684
|
-
deps.log(
|
|
29685
|
-
`running scheduled fan-out for ${repositories.length} consumer agenc${repositories.length === 1 ? "y" : "ies"}`
|
|
29686
|
-
);
|
|
29687
|
-
const clock = deps.now ?? Date.now;
|
|
29688
|
-
let claimed = 0;
|
|
29689
|
-
for (const repository of repositories) {
|
|
29690
|
-
const [owner, repo] = repository.split("/");
|
|
29691
|
-
try {
|
|
29692
|
-
const jobId = `sched-${owner}-${repo}-${clock()}`;
|
|
29693
|
-
const result = await deps.claim(owner, repo, {
|
|
29694
|
-
jobId,
|
|
29695
|
-
repo: repository,
|
|
29696
|
-
runRequest: {
|
|
29697
|
-
requestId: jobId,
|
|
29698
|
-
target: { type: "workflow", id: "scheduled-fanout" },
|
|
29699
|
-
intent: "tick",
|
|
29700
|
-
source: "schedule"
|
|
29701
|
-
}
|
|
29702
|
-
});
|
|
29703
|
-
if (result.ok) {
|
|
29704
|
-
claimed++;
|
|
29705
|
-
deps.log(`[${repository}] scheduled fan-out claimed ${result.machineId}`);
|
|
29706
|
-
} else {
|
|
29707
|
-
deps.log(`[${repository}] scheduled fan-out skipped: ${result.reason ?? "runner unavailable"}`);
|
|
29708
|
-
}
|
|
29709
|
-
} catch (error) {
|
|
29710
|
-
deps.log(`[${repository}] scheduled fan-out error: ${error instanceof Error ? error.message : String(error)}`);
|
|
29711
|
-
}
|
|
29712
|
-
}
|
|
29713
|
-
return { discovered: repositories.length, claimed };
|
|
29714
|
-
}
|
|
29715
|
-
|
|
29716
|
-
// src/servers/pool-serve.ts
|
|
29717
29824
|
init_keys();
|
|
29718
29825
|
|
|
29719
29826
|
// src/pool/registry.ts
|
|
@@ -30349,30 +30456,6 @@ async function poolServe() {
|
|
|
30349
30456
|
const tick = setInterval(() => {
|
|
30350
30457
|
registry.resyncAll().catch((err) => log(`resync tick failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
30351
30458
|
}, refillMs);
|
|
30352
|
-
const discoverAgencies = async () => {
|
|
30353
|
-
if (!appCreds) return registry.activeRepos();
|
|
30354
|
-
const repositories = await discoverAppRepositories(appCreds);
|
|
30355
|
-
for (const access of repositories) repoTokens.set(access.repo.toLowerCase(), access.token);
|
|
30356
|
-
return [.../* @__PURE__ */ new Set([...repositories.map((access) => access.repo), ...registry.activeRepos()])];
|
|
30357
|
-
};
|
|
30358
|
-
let agencyTickInFlight = null;
|
|
30359
|
-
const runLoopTick = () => {
|
|
30360
|
-
if (agencyTickInFlight) return agencyTickInFlight;
|
|
30361
|
-
agencyTickInFlight = runAgencyLoopTick({
|
|
30362
|
-
discover: discoverAgencies,
|
|
30363
|
-
claim: (owner, repo, req) => registry.claim(owner, repo, req),
|
|
30364
|
-
log
|
|
30365
|
-
}).catch((err) => log(`agency Loop tick failed: ${err instanceof Error ? err.message : String(err)}`)).finally(() => {
|
|
30366
|
-
agencyTickInFlight = null;
|
|
30367
|
-
});
|
|
30368
|
-
return agencyTickInFlight;
|
|
30369
|
-
};
|
|
30370
|
-
const loopTickEnabled = (process.env.POOL_LOOP_TICK ?? process.env.POOL_CAPABILITY_TICK ?? "1") !== "0";
|
|
30371
|
-
const loopTickMs = envInt2(
|
|
30372
|
-
process.env.POOL_LOOP_TICK_MS ? "POOL_LOOP_TICK_MS" : "POOL_CAPABILITY_TICK_MS",
|
|
30373
|
-
15 * 6e4
|
|
30374
|
-
);
|
|
30375
|
-
const loopTick = loopTickEnabled ? setInterval(() => void runLoopTick(), loopTickMs) : null;
|
|
30376
30459
|
const server = createServer5(async (req, res) => {
|
|
30377
30460
|
try {
|
|
30378
30461
|
if (!req.method || !req.url) return sendJson2(res, 400, { error: "bad request" });
|
|
@@ -30426,11 +30509,9 @@ async function poolServe() {
|
|
|
30426
30509
|
resolve24();
|
|
30427
30510
|
});
|
|
30428
30511
|
});
|
|
30429
|
-
if (loopTickEnabled) void runLoopTick();
|
|
30430
30512
|
const shutdown = (signal) => {
|
|
30431
30513
|
log(`${signal} \u2014 shutting down`);
|
|
30432
30514
|
clearInterval(tick);
|
|
30433
|
-
if (loopTick) clearInterval(loopTick);
|
|
30434
30515
|
server.close(() => process.exit(0));
|
|
30435
30516
|
};
|
|
30436
30517
|
process.once("SIGINT", () => shutdown("SIGINT"));
|
|
@@ -30442,7 +30523,7 @@ async function poolServe() {
|
|
|
30442
30523
|
|
|
30443
30524
|
// src/servers/runner-serve.ts
|
|
30444
30525
|
import { spawn as spawn10 } from "child_process";
|
|
30445
|
-
import * as
|
|
30526
|
+
import * as fs58 from "fs";
|
|
30446
30527
|
import { createServer as createServer6 } from "http";
|
|
30447
30528
|
var DEFAULT_PORT2 = 8080;
|
|
30448
30529
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -30518,8 +30599,8 @@ async function defaultRunJob(job) {
|
|
|
30518
30599
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
30519
30600
|
const branch = job.ref ?? "main";
|
|
30520
30601
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
30521
|
-
|
|
30522
|
-
|
|
30602
|
+
fs58.rmSync(workdir, { recursive: true, force: true });
|
|
30603
|
+
fs58.mkdirSync(workdir, { recursive: true });
|
|
30523
30604
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
30524
30605
|
const target = job.runRequest.target;
|
|
30525
30606
|
const interactive = target.type === "chat";
|
|
@@ -31107,7 +31188,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
31107
31188
|
const args = parseArgs(argv);
|
|
31108
31189
|
const cwdFlag = argv.indexOf("--cwd");
|
|
31109
31190
|
const definitionCwd = cwdFlag >= 0 && argv[cwdFlag + 1] ? argv[cwdFlag + 1] : process.cwd();
|
|
31110
|
-
const shouldHydrate = !(args.command === "server" && args.serverName === "brain-serve") && !hasExplicitDefinitionsRoot(definitionCwd) && (Boolean(process.env.CONVEX_URL?.trim()) || process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.GITHUB_EVENT_NAME));
|
|
31191
|
+
const shouldHydrate = args.command !== "help" && args.command !== "version" && !(args.command === "server" && args.serverName === "brain-serve") && !hasExplicitDefinitionsRoot(definitionCwd) && (Boolean(process.env.CONVEX_URL?.trim()) || process.env.GITHUB_ACTIONS === "true" && Boolean(process.env.GITHUB_EVENT_NAME));
|
|
31111
31192
|
if (shouldHydrate) {
|
|
31112
31193
|
try {
|
|
31113
31194
|
await hydrateDefinitionsFromEnv(definitionCwd);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "live-agent",
|
|
3
|
+
"action": "live-agent",
|
|
4
|
+
"purpose": "Run one continuation cycle for a selected persistent Agent.",
|
|
5
|
+
"inputSchema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"agent": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Selected Agent slug."
|
|
11
|
+
},
|
|
12
|
+
"intent": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Primary Intent slug recorded by the Loop."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"required": ["agent"],
|
|
18
|
+
"additionalProperties": false
|
|
19
|
+
},
|
|
20
|
+
"outputSchema": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"cursor": { "type": "string" },
|
|
24
|
+
"data": { "type": "object", "additionalProperties": true }
|
|
25
|
+
},
|
|
26
|
+
"additionalProperties": true
|
|
27
|
+
},
|
|
28
|
+
"effects": ["agent-state"],
|
|
29
|
+
"permissions": [],
|
|
30
|
+
"success": "The Agent completes one cycle and persists its continuation state.",
|
|
31
|
+
"failure": "The Agent cycle fails or its continuation state cannot be persisted."
|
|
32
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "live-agent",
|
|
3
|
+
"role": "primitive",
|
|
4
|
+
"kind": "oneshot",
|
|
5
|
+
"inputs": [
|
|
6
|
+
{ "name": "agent", "flag": "--agent", "type": "string", "required": true, "describe": "Live Agent slug." },
|
|
7
|
+
{ "name": "intent", "flag": "--intent", "type": "string", "required": false, "describe": "Primary Intent slug recorded by the Loop." }
|
|
8
|
+
],
|
|
9
|
+
"claudeCode": {
|
|
10
|
+
"model": "inherit",
|
|
11
|
+
"permissionMode": "default",
|
|
12
|
+
"maxTurns": 100,
|
|
13
|
+
"maxThinkingTokens": null,
|
|
14
|
+
"systemPromptAppend": null,
|
|
15
|
+
"enableSubmitTool": true,
|
|
16
|
+
"tools": ["mcp__kody-capability__start_capability", "mcp__kody-submit__submit_state"],
|
|
17
|
+
"hooks": [], "skills": [], "commands": [], "subagents": [], "plugins": [], "mcpServers": []
|
|
18
|
+
},
|
|
19
|
+
"cliTools": [],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"preflight": [{ "script": "loadLiveAgent" }, { "script": "composePrompt" }],
|
|
22
|
+
"postflight": [
|
|
23
|
+
{ "script": "parseJobStateFromAgentResult", "with": { "fenceLabel": "kody-agent-next-state" } },
|
|
24
|
+
{ "script": "saveLiveAgentState" },
|
|
25
|
+
{ "script": "appendCompanyActivity" }
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"inputArtifacts": [],
|
|
29
|
+
"outputArtifacts": []
|
|
30
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
You are a persistent Kody Agent completing one scheduled cycle.
|
|
2
|
+
|
|
3
|
+
## Identity
|
|
4
|
+
|
|
5
|
+
{{agentIdentity}}
|
|
6
|
+
|
|
7
|
+
## Primary Intent
|
|
8
|
+
|
|
9
|
+
{{liveAgentIntent}}
|
|
10
|
+
|
|
11
|
+
## Policies
|
|
12
|
+
|
|
13
|
+
{{liveAgentPolicies}}
|
|
14
|
+
|
|
15
|
+
## Constraints
|
|
16
|
+
|
|
17
|
+
{{liveAgentConstraints}}
|
|
18
|
+
|
|
19
|
+
## Context
|
|
20
|
+
|
|
21
|
+
{{liveAgentContext}}
|
|
22
|
+
|
|
23
|
+
## Assigned Capabilities
|
|
24
|
+
|
|
25
|
+
{{liveAgentCapabilities}}
|
|
26
|
+
|
|
27
|
+
## Previous continuation
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{{jobStateJson}}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Inspect current conditions, decide the best next action toward the Intent, and use only assigned capabilities. Do not create work merely to appear active. If waiting is correct, record what is being awaited.
|
|
34
|
+
|
|
35
|
+
As your final action, call `submit_state` exactly once with:
|
|
36
|
+
- `cursor`: the next continuation cursor;
|
|
37
|
+
- `data`: compact durable continuation data;
|
|
38
|
+
- `done`: always `false` for a live Agent.
|
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.610",
|
|
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",
|
package/templates/kody.yml
CHANGED
|
@@ -50,8 +50,6 @@ on:
|
|
|
50
50
|
types: [created]
|
|
51
51
|
pull_request:
|
|
52
52
|
types: [opened, synchronize, closed]
|
|
53
|
-
schedule:
|
|
54
|
-
- cron: '7/15 * * * *'
|
|
55
53
|
|
|
56
54
|
jobs:
|
|
57
55
|
run:
|
|
@@ -82,7 +80,7 @@ jobs:
|
|
|
82
80
|
GH_PAT: ${{ secrets.GH_PAT }}
|
|
83
81
|
KODY_TOKEN: ${{ secrets.KODY_TOKEN }}
|
|
84
82
|
E2E_GITHUB_TOKEN: ${{ secrets.E2E_GITHUB_TOKEN }}
|
|
85
|
-
|
|
83
|
+
MINIMAX_API_KEY: ${{ secrets.MINIMAX_API_KEY }}
|
|
86
84
|
KODY_APP_ID: ${{ secrets.KODY_APP_ID }}
|
|
87
85
|
KODY_APP_PRIVATE_KEY: ${{ secrets.KODY_APP_PRIVATE_KEY }}
|
|
88
86
|
SESSION_ID: ${{ inputs.sessionId }}
|