@kody-ade/kody-engine 0.4.138 → 0.4.139
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
|
@@ -312,6 +312,52 @@ var init_verifyMcp = __esm({
|
|
|
312
312
|
}
|
|
313
313
|
});
|
|
314
314
|
|
|
315
|
+
// src/submitMcp.ts
|
|
316
|
+
var submitMcp_exports = {};
|
|
317
|
+
__export(submitMcp_exports, {
|
|
318
|
+
buildSubmitMcpServer: () => buildSubmitMcpServer
|
|
319
|
+
});
|
|
320
|
+
import { createSdkMcpServer as createSdkMcpServer2, tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
|
|
321
|
+
import { z as z2 } from "zod";
|
|
322
|
+
function buildSubmitMcpServer() {
|
|
323
|
+
let submitted;
|
|
324
|
+
const submitTool = tool2(
|
|
325
|
+
"submit_state",
|
|
326
|
+
"Persist this tick's next state. Call this EXACTLY ONCE, at the very end, when you've finished your work \u2014 it is the ONLY way your decision is saved. Pass your next `cursor` (string), your next `data` (object \u2014 carry prior data forward and mutate what you acted on), and `done` (boolean). After calling it you are finished; do not take further actions.",
|
|
327
|
+
{
|
|
328
|
+
cursor: z2.string().describe('The next cursor value (e.g. "idle"). Must be a non-empty string.'),
|
|
329
|
+
data: z2.record(z2.string(), z2.unknown()).describe("The next `data` object. Carry forward prior data and mutate only what you acted on this tick."),
|
|
330
|
+
done: z2.boolean().describe("true only if this duty is permanently finished; evergreen duties stay false.")
|
|
331
|
+
},
|
|
332
|
+
async (args) => {
|
|
333
|
+
submitted = {
|
|
334
|
+
cursor: String(args.cursor ?? ""),
|
|
335
|
+
data: args.data ?? {},
|
|
336
|
+
done: Boolean(args.done)
|
|
337
|
+
};
|
|
338
|
+
return {
|
|
339
|
+
content: [
|
|
340
|
+
{
|
|
341
|
+
type: "text",
|
|
342
|
+
text: "State recorded. You are done for this tick \u2014 no further action needed."
|
|
343
|
+
}
|
|
344
|
+
]
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
const server = createSdkMcpServer2({
|
|
349
|
+
name: "kody-submit",
|
|
350
|
+
version: "0.1.0",
|
|
351
|
+
tools: [submitTool]
|
|
352
|
+
});
|
|
353
|
+
return { server, getSubmitted: () => submitted };
|
|
354
|
+
}
|
|
355
|
+
var init_submitMcp = __esm({
|
|
356
|
+
"src/submitMcp.ts"() {
|
|
357
|
+
"use strict";
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
315
361
|
// src/issue.ts
|
|
316
362
|
import { execFileSync } from "child_process";
|
|
317
363
|
function ghToken() {
|
|
@@ -880,7 +926,7 @@ var init_loadPriorArt = __esm({
|
|
|
880
926
|
// package.json
|
|
881
927
|
var package_default = {
|
|
882
928
|
name: "@kody-ade/kody-engine",
|
|
883
|
-
version: "0.4.
|
|
929
|
+
version: "0.4.139",
|
|
884
930
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
885
931
|
license: "MIT",
|
|
886
932
|
type: "module",
|
|
@@ -1514,6 +1560,7 @@ async function runAgent(opts) {
|
|
|
1514
1560
|
const turnTimeoutMs = resolveTurnTimeoutMs(opts);
|
|
1515
1561
|
let ndjsonWriteFailed = false;
|
|
1516
1562
|
let ndjsonWriteError;
|
|
1563
|
+
let getSubmitted;
|
|
1517
1564
|
try {
|
|
1518
1565
|
const queryOptions = {
|
|
1519
1566
|
model: opts.model.model,
|
|
@@ -1541,6 +1588,12 @@ async function runAgent(opts) {
|
|
|
1541
1588
|
});
|
|
1542
1589
|
mcpEntries.push(["kody-verify", verifyServer]);
|
|
1543
1590
|
}
|
|
1591
|
+
if (opts.enableSubmitTool) {
|
|
1592
|
+
const { buildSubmitMcpServer: buildSubmitMcpServer2 } = await Promise.resolve().then(() => (init_submitMcp(), submitMcp_exports));
|
|
1593
|
+
const submitHandle = buildSubmitMcpServer2();
|
|
1594
|
+
getSubmitted = submitHandle.getSubmitted;
|
|
1595
|
+
mcpEntries.push(["kody-submit", submitHandle.server]);
|
|
1596
|
+
}
|
|
1544
1597
|
if (mcpEntries.length > 0) {
|
|
1545
1598
|
queryOptions.mcpServers = Object.fromEntries(mcpEntries);
|
|
1546
1599
|
}
|
|
@@ -1706,10 +1759,12 @@ async function runAgent(opts) {
|
|
|
1706
1759
|
`);
|
|
1707
1760
|
}
|
|
1708
1761
|
const finalText = resultTexts.join("\n\n---\n\n");
|
|
1762
|
+
const submittedState = getSubmitted?.();
|
|
1709
1763
|
return {
|
|
1710
1764
|
outcome,
|
|
1711
1765
|
outcomeKind,
|
|
1712
1766
|
finalText,
|
|
1767
|
+
...submittedState ? { submittedState } : {},
|
|
1713
1768
|
error: errorMessage,
|
|
1714
1769
|
ndjsonPath,
|
|
1715
1770
|
durationMs: Date.now() - startedAt,
|
|
@@ -3186,6 +3241,7 @@ function parseClaudeCode(p, raw) {
|
|
|
3186
3241
|
systemPromptAppend: typeof r.systemPromptAppend === "string" ? r.systemPromptAppend : null,
|
|
3187
3242
|
cacheable: r.cacheable === true,
|
|
3188
3243
|
enableVerifyTool: r.enableVerifyTool === true,
|
|
3244
|
+
enableSubmitTool: r.enableSubmitTool === true,
|
|
3189
3245
|
verifyAttempts: typeof r.verifyAttempts === "number" && r.verifyAttempts > 0 ? r.verifyAttempts : null,
|
|
3190
3246
|
tools,
|
|
3191
3247
|
hooks: Array.isArray(r.hooks) ? r.hooks : [],
|
|
@@ -9313,6 +9369,17 @@ var parseJobStateFromAgentResult = async (ctx, _profile, agentResult, args) => {
|
|
|
9313
9369
|
}
|
|
9314
9370
|
const loaded = ctx.data.jobState;
|
|
9315
9371
|
const prevRev = loaded?.state.rev ?? 0;
|
|
9372
|
+
const submitted = agentResult.submittedState;
|
|
9373
|
+
if (submitted && typeof submitted.cursor === "string" && submitted.cursor.length > 0) {
|
|
9374
|
+
ctx.data.nextJobState = {
|
|
9375
|
+
version: 1,
|
|
9376
|
+
rev: prevRev + 1,
|
|
9377
|
+
cursor: submitted.cursor,
|
|
9378
|
+
data: submitted.data ?? {},
|
|
9379
|
+
done: Boolean(submitted.done)
|
|
9380
|
+
};
|
|
9381
|
+
return;
|
|
9382
|
+
}
|
|
9316
9383
|
const result = extractNextStateFromText(agentResult.finalText, fenceLabel, prevRev);
|
|
9317
9384
|
if (result.error) {
|
|
9318
9385
|
ctx.data.nextStateParseError = result.error.startsWith("missing `") ? `agent did not emit a \`${fenceLabel}\` fenced block` : result.error;
|
|
@@ -12512,21 +12579,21 @@ function firstRequiredFailure(results, tools) {
|
|
|
12512
12579
|
}
|
|
12513
12580
|
return null;
|
|
12514
12581
|
}
|
|
12515
|
-
function verifyOne(
|
|
12516
|
-
const result = { name:
|
|
12517
|
-
let present = runShell(
|
|
12518
|
-
if (!present &&
|
|
12519
|
-
runShell(
|
|
12520
|
-
present = runShell(
|
|
12582
|
+
function verifyOne(tool3, cwd) {
|
|
12583
|
+
const result = { name: tool3.name, present: false, verified: false };
|
|
12584
|
+
let present = runShell(tool3.install.checkCommand, cwd);
|
|
12585
|
+
if (!present && tool3.install.installCommand) {
|
|
12586
|
+
runShell(tool3.install.installCommand, cwd, 12e4);
|
|
12587
|
+
present = runShell(tool3.install.checkCommand, cwd);
|
|
12521
12588
|
}
|
|
12522
12589
|
result.present = present;
|
|
12523
12590
|
if (!present) {
|
|
12524
|
-
result.error = `tool "${
|
|
12591
|
+
result.error = `tool "${tool3.name}" not on PATH (check: ${tool3.install.checkCommand})`;
|
|
12525
12592
|
return result;
|
|
12526
12593
|
}
|
|
12527
|
-
const verified = runShell(
|
|
12594
|
+
const verified = runShell(tool3.verify, cwd);
|
|
12528
12595
|
result.verified = verified;
|
|
12529
|
-
if (!verified) result.error = `tool "${
|
|
12596
|
+
if (!verified) result.error = `tool "${tool3.name}" failed verify: ${tool3.verify}`;
|
|
12530
12597
|
return result;
|
|
12531
12598
|
}
|
|
12532
12599
|
function runShell(cmd, cwd, timeoutMs = 3e4) {
|
|
@@ -12666,6 +12733,7 @@ async function runExecutable(profileName, input) {
|
|
|
12666
12733
|
systemPromptAppend: [DISCIPLINE, profile.claudeCode.systemPromptAppend, taskArtifacts?.promptAddendum].filter((s) => typeof s === "string" && s.length > 0).join("\n\n") || void 0,
|
|
12667
12734
|
cacheable: profile.claudeCode.cacheable,
|
|
12668
12735
|
enableVerifyTool: profile.claudeCode.enableVerifyTool,
|
|
12736
|
+
enableSubmitTool: profile.claudeCode.enableSubmitTool,
|
|
12669
12737
|
verifyToolMaxAttempts: profile.claudeCode.verifyAttempts ?? null,
|
|
12670
12738
|
verifyConfig: profile.claudeCode.enableVerifyTool ? config : void 0,
|
|
12671
12739
|
executableName: profileName,
|
|
@@ -32,23 +32,25 @@ This is the state you wrote at the end of the previous tick (or `null` if this i
|
|
|
32
32
|
2. **Re-read the job body.** It may have changed since the last tick.
|
|
33
33
|
3. **Execute exactly the work the body's `## Job` section describes**, subject to its `## Allowed Commands` and `## Restrictions`. Use the `## State` section to interpret and update `data`.
|
|
34
34
|
4. **Optionally post a short narration** wherever the job tells you to (typically a PR comment alongside the action). Keep it terse.
|
|
35
|
-
5. **
|
|
35
|
+
5. **Submit the new state** by calling the `submit_state` tool (see contract below). Do not include `version` or `rev` — the postflight script manages those.
|
|
36
36
|
|
|
37
37
|
## Output contract (MANDATORY, exactly once, at the end)
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Call the **`submit_state`** tool exactly once, as the final step, with your next state:
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"done": <true|false>
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
````
|
|
41
|
+
- `cursor` — your next cursor (string, e.g. `"idle"`).
|
|
42
|
+
- `data` — your next `data` object. Carry forward prior `data` and mutate only what you acted on this tick.
|
|
43
|
+
- `done` — `true` only if the duty is permanently finished; evergreen duties stay `false`.
|
|
44
|
+
|
|
45
|
+
This is the ONLY way your decision is saved. If you don't call it, the tick fails and the state is NOT updated — on the next wake you'll see the same prior state and can retry.
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
> Backstop (legacy): if the `submit_state` tool is unavailable, end your reply with the same JSON in a single fenced block tagged `kody-job-next-state` instead:
|
|
48
|
+
>
|
|
49
|
+
> ````
|
|
50
|
+
> ```kody-job-next-state
|
|
51
|
+
> { "cursor": "<next>", "data": { ... }, "done": <true|false> }
|
|
52
|
+
> ```
|
|
53
|
+
> ````
|
|
52
54
|
|
|
53
55
|
## Rules
|
|
54
56
|
|
|
@@ -228,6 +228,13 @@ export interface ClaudeCodeSpec {
|
|
|
228
228
|
* Default false.
|
|
229
229
|
*/
|
|
230
230
|
enableVerifyTool?: boolean
|
|
231
|
+
/**
|
|
232
|
+
* Opt-in: expose an in-process `submit_state` tool the agent calls to
|
|
233
|
+
* persist its next state, instead of relying on a trailing fenced
|
|
234
|
+
* `kody-job-next-state` block it must remember to emit. Used by job-tick.
|
|
235
|
+
* The fenced block stays supported as a fallback. Default false.
|
|
236
|
+
*/
|
|
237
|
+
enableSubmitTool?: boolean
|
|
231
238
|
/**
|
|
232
239
|
* Hard cap on verify-tool invocations per agent session when
|
|
233
240
|
* `enableVerifyTool` is true. Default 4 (≈3 fix iterations after the
|
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.139",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|