@kody-ade/kody-engine 0.4.261 → 0.4.262
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 +15 -15
- package/dist/bin/kody.js +807 -816
- package/dist/capabilities/agent-factory/capability.md +10 -0
- package/dist/capabilities/agent-factory/profile.json +7 -0
- package/dist/capabilities/run/capability.md +10 -0
- package/dist/capabilities/run/profile.json +6 -0
- package/dist/executables/agent-factory/profile.json +47 -0
- package/dist/executables/agent-factory/prompt.md +68 -0
- package/dist/executables/run/profile.json +83 -0
- package/dist/executables/run/prompt.md +81 -0
- package/dist/executables/types.ts +558 -0
- package/dist/plugins/hooks/block-write.json +1 -1
- package/kody.config.schema.json +8 -8
- package/package.json +2 -2
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types shared by the generic executor and executables.
|
|
3
|
+
*
|
|
4
|
+
* The executor reads a Profile, validates the user's CLI args against
|
|
5
|
+
* Profile.inputs, then runs the declared preflight scripts → agent →
|
|
6
|
+
* postflight scripts. The executor knows nothing about any specific role
|
|
7
|
+
* (build, review, plan, etc.) — it only executes what the profile declares.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { AgentResult } from "../agent.js"
|
|
11
|
+
import type { KodyConfig, ReasoningEffort } from "../config.js"
|
|
12
|
+
import type { Phase } from "../state.js"
|
|
13
|
+
|
|
14
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
// Profile shape (mirrors the JSON on disk).
|
|
16
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
export type CapabilityKind = "observe" | "act" | "verify"
|
|
19
|
+
|
|
20
|
+
export interface Profile {
|
|
21
|
+
name: string
|
|
22
|
+
/**
|
|
23
|
+
* Public action name owned by a capability. A user may type `@kody <action>`;
|
|
24
|
+
* dispatch resolves that action to the capability, then the capability selects the
|
|
25
|
+
* implementation executable. Absent → the capability slug/name is the action.
|
|
26
|
+
*/
|
|
27
|
+
action?: string
|
|
28
|
+
/**
|
|
29
|
+
* Optional agent this executable runs *as*. When set, the executor
|
|
30
|
+
* loads hydrated `.kody/agents/<agent>.md` and injects that agent (authoritative
|
|
31
|
+
* identity) ahead of the executable's own system-prompt append. This is the
|
|
32
|
+
* unification hook: a "capability" is just an executable + an agent. Absent →
|
|
33
|
+
* runs with no agent (unchanged legacy behaviour). A declared-but-missing
|
|
34
|
+
* agent file is fatal at run time (see src/agents.ts).
|
|
35
|
+
*/
|
|
36
|
+
agent?: string
|
|
37
|
+
describe: string
|
|
38
|
+
/**
|
|
39
|
+
* Author-facing capability promise for a capability/executable. This classifies the
|
|
40
|
+
* shape of result it should return; it does not change executor control flow.
|
|
41
|
+
*/
|
|
42
|
+
capabilityKind?: CapabilityKind
|
|
43
|
+
/**
|
|
44
|
+
* Semantic role — what this executable IS, not when it runs.
|
|
45
|
+
* - primitive: single-step agent executor (flow → agent → verify → commit → PR).
|
|
46
|
+
* - orchestrator: no-agent, drives primitives via a postflight transition table
|
|
47
|
+
* (comment-based, one GHA run per step).
|
|
48
|
+
* - container: no-agent, runs declared `children` sequentially in-process
|
|
49
|
+
* (one GHA run for the whole flow). Routing is done by per-child
|
|
50
|
+
* `next` maps over action types — no @kody comments dispatched.
|
|
51
|
+
* - watch: scheduled observer that inspects repo state and may trigger other executables.
|
|
52
|
+
* - utility: no-agent, one-off administrative work (scaffolding, release, etc.).
|
|
53
|
+
*
|
|
54
|
+
* Roles enforce shape at profile-load time and let help/dispatch treat
|
|
55
|
+
* executables differently by category.
|
|
56
|
+
*/
|
|
57
|
+
role: "primitive" | "orchestrator" | "container" | "watch" | "utility"
|
|
58
|
+
/**
|
|
59
|
+
* Capability contract profiles can point at a separate implementation by name.
|
|
60
|
+
* `executable` remains a legacy alias while old assets migrate.
|
|
61
|
+
*/
|
|
62
|
+
implementation?: string
|
|
63
|
+
executable?: string
|
|
64
|
+
implementations?: string[]
|
|
65
|
+
executables?: string[]
|
|
66
|
+
/**
|
|
67
|
+
* Execution model — orthogonal to `role`.
|
|
68
|
+
* `oneshot` (default): single invocation on demand.
|
|
69
|
+
* `scheduled`: fires periodically via an external cron (typically GHA
|
|
70
|
+
* `schedule:`). Scheduled profiles must declare a `schedule` cron string.
|
|
71
|
+
*/
|
|
72
|
+
kind: "oneshot" | "scheduled"
|
|
73
|
+
/**
|
|
74
|
+
* Locked-toolbox palette (unified successor to a markdown capability's `tools:`
|
|
75
|
+
* metadata). When non-empty, loadCapabilityState sets ctx.data.capabilityTools so the
|
|
76
|
+
* executor spins up the in-process kody-capability MCP server and the agent runs
|
|
77
|
+
* MCP-only (Bash/Read revoked unless also in claudeCode.tools). Absent →
|
|
78
|
+
* normal SDK tools.
|
|
79
|
+
*/
|
|
80
|
+
capabilityTools?: string[]
|
|
81
|
+
/**
|
|
82
|
+
* GitHub logins (no leading `@`) this capability's output should mention. Rendered
|
|
83
|
+
* to `@a @b` and exposed to the prompt as {{mentions}} (and as the capability-MCP
|
|
84
|
+
* operator mention), mirroring a markdown capability's `mentions:` metadata.
|
|
85
|
+
*/
|
|
86
|
+
mentions?: string[]
|
|
87
|
+
/** Cron expression for scheduled profiles (e.g. "0 8 * * MON"). */
|
|
88
|
+
schedule?: string
|
|
89
|
+
/**
|
|
90
|
+
* Task-state phase label emitted when this executable completes successfully.
|
|
91
|
+
* Failing actions always set phase to "failed" regardless. Omitted → "idle".
|
|
92
|
+
* Lets state.ts stay generic — phase semantics live on the profile.
|
|
93
|
+
*/
|
|
94
|
+
phase?: Phase
|
|
95
|
+
inputs: InputSpec[]
|
|
96
|
+
claudeCode: ClaudeCodeSpec
|
|
97
|
+
cliTools: CliToolSpec[]
|
|
98
|
+
/**
|
|
99
|
+
* Optional lifecycle macro. When set, the profile loader applies a
|
|
100
|
+
* predefined preflight/postflight wrapper around `scripts.preflight` and
|
|
101
|
+
* `scripts.postflight` before returning the profile. Registry of lifecycles
|
|
102
|
+
* lives in src/lifecycles/. Unknown values are rejected at load time.
|
|
103
|
+
*
|
|
104
|
+
* Lifecycles exist to consolidate orchestration boilerplate (label,
|
|
105
|
+
* context loading, verify, commit, comment) that recurs across many
|
|
106
|
+
* executables. Per-executable specifics still go in `scripts.preflight`
|
|
107
|
+
* and `scripts.postflight` — the lifecycle wraps them, it doesn't
|
|
108
|
+
* replace them.
|
|
109
|
+
*/
|
|
110
|
+
lifecycle?: string
|
|
111
|
+
/**
|
|
112
|
+
* Lifecycle-specific configuration. Shape depends on `lifecycle`. Validated
|
|
113
|
+
* by each lifecycle expander, not by the generic profile parser.
|
|
114
|
+
*/
|
|
115
|
+
lifecycleConfig?: Record<string, unknown>
|
|
116
|
+
scripts: {
|
|
117
|
+
preflight: ScriptEntry[]
|
|
118
|
+
postflight: ScriptEntry[]
|
|
119
|
+
}
|
|
120
|
+
outputContract?: OutputContract
|
|
121
|
+
/**
|
|
122
|
+
* Declared artifacts consumed by this executable. The resolveArtifacts
|
|
123
|
+
* preflight loads each into ctx.data.artifacts[name] from the task-state
|
|
124
|
+
* comment. If `required: true` and the artifact is absent, the executable
|
|
125
|
+
* fails fast.
|
|
126
|
+
*/
|
|
127
|
+
inputArtifacts: InputArtifactSpec[]
|
|
128
|
+
/**
|
|
129
|
+
* Declared artifacts produced by this executable. The persistArtifacts
|
|
130
|
+
* postflight reads the named source field from ctx.data and writes an
|
|
131
|
+
* Artifact entry into the task state's `artifacts` map.
|
|
132
|
+
*/
|
|
133
|
+
outputArtifacts: OutputArtifactSpec[]
|
|
134
|
+
/**
|
|
135
|
+
* Container children — required when role === "container", forbidden otherwise.
|
|
136
|
+
* Defines the in-process step sequence and routing map. See ContainerChild.
|
|
137
|
+
*/
|
|
138
|
+
children?: ContainerChild[]
|
|
139
|
+
/**
|
|
140
|
+
* Whether the container should `git reset --hard HEAD` between
|
|
141
|
+
* children to discard tracked-file modifications a prior child left
|
|
142
|
+
* behind. Default `true` (preserves the legacy bug-safe behaviour
|
|
143
|
+
* — see executor.ts:runContainerLoop notes). Set `false` for
|
|
144
|
+
* containers whose children are expected to share intermediate
|
|
145
|
+
* state (e.g. bug's `reproduce` writing a failing test that `run`
|
|
146
|
+
* then makes pass). Only honoured when `role === "container"`.
|
|
147
|
+
*/
|
|
148
|
+
resetBetweenChildren?: boolean
|
|
149
|
+
/**
|
|
150
|
+
* Phase 5 in-process handoff: when true, the container's loop runs
|
|
151
|
+
* the shared context loaders (loadConventions, loadPriorArt,
|
|
152
|
+
* loadMemoryContext, loadCoverageRules) ONCE after its own preflight
|
|
153
|
+
* completes, then passes the resulting `ctx.data` snapshot to every
|
|
154
|
+
* child via `ExecutorInput.preloadedData`. Each child's loaders take
|
|
155
|
+
* their fast path (added in 0.4.63) and skip the redundant
|
|
156
|
+
* GitHub/filesystem round-trips.
|
|
157
|
+
*
|
|
158
|
+
* Default `false` (opt-in) so the change is gated to containers
|
|
159
|
+
* that have been verified end-to-end. Only honoured when
|
|
160
|
+
* `role === "container"`.
|
|
161
|
+
*/
|
|
162
|
+
preloadContext?: boolean
|
|
163
|
+
/** Absolute directory the profile was loaded from. Used to resolve prompt.md. */
|
|
164
|
+
dir: string
|
|
165
|
+
/**
|
|
166
|
+
* Prompt template files captured (by absolute path) at load time, BEFORE any
|
|
167
|
+
* preflight runs. composePrompt prefers these over a fresh disk read so the
|
|
168
|
+
* template survives working-tree churn from runFlow's branch setup — on the CI
|
|
169
|
+
* runner a branch checkout can drop the tracked-but-ignore-negated
|
|
170
|
+
* `.kody/executables/<name>/` dir, and reading prompt.md afterwards fails with
|
|
171
|
+
* ENOENT even though profile.json (read here, earlier) loaded fine.
|
|
172
|
+
*/
|
|
173
|
+
promptTemplates?: Record<string, string>
|
|
174
|
+
/**
|
|
175
|
+
* Subagent markdown captured (by declared name) at load time, BEFORE any
|
|
176
|
+
* task branch switch — same rationale as promptTemplates. loadSubagents
|
|
177
|
+
* prefers this snapshot so a capability's `agents/` surviving only on the default
|
|
178
|
+
* checkout (e.g. `.kody/capabilities/<slug>/agents/` absent on a PR branch) doesn't
|
|
179
|
+
* crash a PR-targeted capability. Populated by captureSubagentTemplates.
|
|
180
|
+
*/
|
|
181
|
+
subagentTemplates?: Record<string, string>
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* One step in a container's child sequence.
|
|
186
|
+
*
|
|
187
|
+
* The container executor runs the first child, reads the resulting action
|
|
188
|
+
* type from `state.core.lastOutcome`, then looks it up in `next`:
|
|
189
|
+
* - exact match → either the name of another child in this container, or
|
|
190
|
+
* the literal "done" / "abort"
|
|
191
|
+
* - "*" wildcard → fallback when no exact match
|
|
192
|
+
* - no match → container aborts
|
|
193
|
+
*/
|
|
194
|
+
export interface ContainerChild {
|
|
195
|
+
/** Name of the executable to invoke (must resolve via the registry). */
|
|
196
|
+
exec: string
|
|
197
|
+
/**
|
|
198
|
+
* Where to source the target identifier from when invoking this child.
|
|
199
|
+
* - "issue": pass --issue <ctx.args.issue>
|
|
200
|
+
* - "pr": parse PR number from state.core.prUrl, pass --pr <N>.
|
|
201
|
+
* If state.core.prUrl is not set, the container aborts with
|
|
202
|
+
* an AGENT_NOT_RUN action.
|
|
203
|
+
*/
|
|
204
|
+
target: "issue" | "pr"
|
|
205
|
+
/**
|
|
206
|
+
* Map from action.type → next step. Each value must be the name of another
|
|
207
|
+
* child in this container, "done" (exit 0), or "abort" (exit 1). Lookup is
|
|
208
|
+
* exact-match first, then "*" as a wildcard fallback.
|
|
209
|
+
*/
|
|
210
|
+
next: Record<string, string>
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface InputArtifactSpec {
|
|
214
|
+
/** Artifact name (the key in state.artifacts). */
|
|
215
|
+
name: string
|
|
216
|
+
/** If true, the executable fails when this artifact is missing from state. */
|
|
217
|
+
required?: boolean
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface OutputArtifactSpec {
|
|
221
|
+
/** Artifact name (the key in state.artifacts). */
|
|
222
|
+
name: string
|
|
223
|
+
/** Informational format tag ("markdown", "text", …). */
|
|
224
|
+
format: string
|
|
225
|
+
/** Dotted path into ctx.data to read the payload from (e.g. "prSummary"). */
|
|
226
|
+
from: string
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface InputSpec {
|
|
230
|
+
name: string
|
|
231
|
+
flag: string
|
|
232
|
+
type: "int" | "string" | "bool" | "enum"
|
|
233
|
+
/** Allowed values for `type: "enum"`. */
|
|
234
|
+
values?: string[]
|
|
235
|
+
required?: boolean
|
|
236
|
+
/**
|
|
237
|
+
* Only required when another input matches one of these values.
|
|
238
|
+
* e.g. `{ mode: "run" }` or `{ mode: ["fix", "fix-ci", "resolve"] }`.
|
|
239
|
+
*/
|
|
240
|
+
requiredWhen?: Record<string, string | string[]>
|
|
241
|
+
/**
|
|
242
|
+
* When true, this input collects any free-text left over from comment
|
|
243
|
+
* dispatch after flag/enum/bool parsing. Only one input per profile may
|
|
244
|
+
* set this. Used by e.g. `fix.feedback` so `@kody please change X` lands
|
|
245
|
+
* "please change X" in `feedback` without hardcoding that in the router.
|
|
246
|
+
*/
|
|
247
|
+
bindsCommentRest?: boolean
|
|
248
|
+
describe: string
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface ClaudeCodeSpec {
|
|
252
|
+
/** "inherit" → use KodyConfig.agent.model. Or a concrete "provider/model". */
|
|
253
|
+
model: string
|
|
254
|
+
permissionMode: "default" | "acceptEdits" | "plan" | "bypassPermissions"
|
|
255
|
+
/** null = unbounded. */
|
|
256
|
+
maxTurns: number | null
|
|
257
|
+
/** Extended-thinking token budget. null = SDK default. */
|
|
258
|
+
maxThinkingTokens: number | null
|
|
259
|
+
/** User-facing effort level. When set, preferred over maxThinkingTokens. */
|
|
260
|
+
reasoningEffort?: ReasoningEffort | null
|
|
261
|
+
/**
|
|
262
|
+
* Watchdog: abort the agent if no SDK message arrives within this many
|
|
263
|
+
* seconds. Per-profile override for the global 600s default. Useful on
|
|
264
|
+
* `run`/`fix` stages where a long test suite can leave the SDK silent
|
|
265
|
+
* longer than the default. Set to 0 or a negative number to disable
|
|
266
|
+
* the watchdog entirely. null/undefined → use the global default.
|
|
267
|
+
*/
|
|
268
|
+
maxTurnTimeoutSec?: number | null
|
|
269
|
+
/** Text appended on top of Claude Code's baseline system prompt. */
|
|
270
|
+
systemPromptAppend: string | null
|
|
271
|
+
/**
|
|
272
|
+
* Cross-process prompt caching opt-in. When true, the agent invocation
|
|
273
|
+
* sets `systemPrompt.excludeDynamicSections: true` so per-user dynamic
|
|
274
|
+
* content (cwd, git status, auto-memory) is stripped from the preset
|
|
275
|
+
* and re-injected as the first user message. The remaining preset
|
|
276
|
+
* becomes byte-identical across runs and benefits from Anthropic's
|
|
277
|
+
* 5-min server-side prompt cache. Recommended for hot-path stages
|
|
278
|
+
* (`run`, `fix`, `classify`) where the same workflow fires many
|
|
279
|
+
* times in a short window.
|
|
280
|
+
*
|
|
281
|
+
* Default: false (preserves legacy behaviour). No-op if the SDK does
|
|
282
|
+
* not support `excludeDynamicSections` (forward-compatible).
|
|
283
|
+
*/
|
|
284
|
+
cacheable?: boolean
|
|
285
|
+
/**
|
|
286
|
+
* Phase 3 opt-in: expose an in-process `verify` MCP tool to the agent
|
|
287
|
+
* so it can iterate on typecheck/lint/test failures inside one SDK
|
|
288
|
+
* session instead of needing a `fix-ci` round trip. The tool is
|
|
289
|
+
* bounded by `verifyAttempts` (default 4). The postflight `verify`
|
|
290
|
+
* script still runs after the agent finishes as the final ratifier.
|
|
291
|
+
* Default false.
|
|
292
|
+
*/
|
|
293
|
+
enableVerifyTool?: boolean
|
|
294
|
+
/**
|
|
295
|
+
* Opt-in: expose an in-process `submit_state` tool the agent calls to
|
|
296
|
+
* persist its next state, instead of relying on a trailing fenced
|
|
297
|
+
* `kody-job-next-state` block it must remember to emit. Used by capability-tick.
|
|
298
|
+
* The fenced block stays supported as a fallback. Default false.
|
|
299
|
+
*/
|
|
300
|
+
enableSubmitTool?: boolean
|
|
301
|
+
/**
|
|
302
|
+
* Hard cap on verify-tool invocations per agent session when
|
|
303
|
+
* `enableVerifyTool` is true. Default 4 (≈3 fix iterations after the
|
|
304
|
+
* first attempt). Set to 0 or omit to use the default.
|
|
305
|
+
*/
|
|
306
|
+
verifyAttempts?: number | null
|
|
307
|
+
/** SDK built-in tools this executable is allowed to use (capability pack). */
|
|
308
|
+
tools: string[]
|
|
309
|
+
/**
|
|
310
|
+
* Names of bundled hook configs to load (from src/plugins/hooks/<name>.json).
|
|
311
|
+
* Each referenced file is a Claude Code hooks JSON ({ hooks: { PreToolUse: [...] } }).
|
|
312
|
+
* Merged into a synthetic plugin at runtime.
|
|
313
|
+
*/
|
|
314
|
+
hooks: string[]
|
|
315
|
+
/** Names of bundled skills to load (from src/plugins/skills/<name>/SKILL.md). */
|
|
316
|
+
skills: string[]
|
|
317
|
+
/** Names of bundled slash commands to load (from src/plugins/commands/<name>.md). */
|
|
318
|
+
commands: string[]
|
|
319
|
+
/** Names of bundled subagents to load (from src/plugins/agents/<name>.md). */
|
|
320
|
+
subagents: string[]
|
|
321
|
+
/**
|
|
322
|
+
* External plugin directory paths (absolute, or relative to the profile dir).
|
|
323
|
+
* Loaded as-is by the SDK via { type: 'local', path }.
|
|
324
|
+
*/
|
|
325
|
+
plugins: string[]
|
|
326
|
+
mcpServers: McpServerSpec[]
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface McpServerSpec {
|
|
330
|
+
name: string
|
|
331
|
+
command: string
|
|
332
|
+
args?: string[]
|
|
333
|
+
env?: Record<string, string>
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface CliToolSpec {
|
|
337
|
+
name: string
|
|
338
|
+
install: {
|
|
339
|
+
required: boolean
|
|
340
|
+
checkCommand: string
|
|
341
|
+
installCommand?: string
|
|
342
|
+
}
|
|
343
|
+
verify: string
|
|
344
|
+
usage: string
|
|
345
|
+
allowedUses: string[]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface ScriptEntry {
|
|
349
|
+
/**
|
|
350
|
+
* Name of a registered TS function in src/scripts/index.ts. Mutually
|
|
351
|
+
* exclusive with `shell` — exactly one must be set.
|
|
352
|
+
*/
|
|
353
|
+
script?: string
|
|
354
|
+
/**
|
|
355
|
+
* Filename of a shell script colocated with the executable
|
|
356
|
+
* (e.g. "apply-prefer.sh"). Resolved relative to the profile's
|
|
357
|
+
* directory. Invoked via `bash <path> <with-args>` with ctx.args
|
|
358
|
+
* exposed as env vars (KODY_ARG_<UPPER_NAME>=<value>). A stdout
|
|
359
|
+
* line `KODY_SKIP_AGENT=true` signals the executor to bypass the
|
|
360
|
+
* agent. Non-zero exit is treated as a preflight failure.
|
|
361
|
+
*/
|
|
362
|
+
shell?: string
|
|
363
|
+
/**
|
|
364
|
+
* Optional conditional. Keys are dotted paths into the context (e.g.
|
|
365
|
+
* "args.mode"). Values are a single primitive or an array of primitives.
|
|
366
|
+
* The script runs only when every key matches. Missing `runWhen` = always.
|
|
367
|
+
*/
|
|
368
|
+
runWhen?: Record<string, string | number | boolean | Array<string | number | boolean>>
|
|
369
|
+
/**
|
|
370
|
+
* Optional per-call arguments passed to the script as the last positional
|
|
371
|
+
* parameter. Used by the orchestrator's transition table so the same
|
|
372
|
+
* dispatcher script can be reused with different `next` targets.
|
|
373
|
+
*/
|
|
374
|
+
with?: Record<string, string | number | boolean>
|
|
375
|
+
/**
|
|
376
|
+
* Optional shell-script timeout in seconds. Only honored on `shell` entries.
|
|
377
|
+
* Falls back to `KODY_SHELL_TIMEOUT_SEC` env var, then the 300s default.
|
|
378
|
+
* Long-running shells (release publish, large repo verify) should declare
|
|
379
|
+
* a higher value rather than relying on the default and getting SIGKILLed
|
|
380
|
+
* with an opaque "exited -1".
|
|
381
|
+
*/
|
|
382
|
+
timeoutSec?: number
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface OutputContract {
|
|
386
|
+
finalMessage?: {
|
|
387
|
+
onSuccess?: string[]
|
|
388
|
+
onFailure?: string[]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export interface CapabilityAlert {
|
|
393
|
+
level?: "info" | "warning" | "error"
|
|
394
|
+
message: string
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export interface CapabilitySuggestedAction {
|
|
398
|
+
action: string
|
|
399
|
+
args?: Record<string, unknown>
|
|
400
|
+
reason?: string
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export interface CapabilityResourceRef {
|
|
404
|
+
type: string
|
|
405
|
+
id?: string | number
|
|
406
|
+
number?: number
|
|
407
|
+
url?: string
|
|
408
|
+
name?: string
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export interface CapabilityEvidenceItem {
|
|
412
|
+
source?: string
|
|
413
|
+
message: string
|
|
414
|
+
url?: string
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export interface ObserveResult {
|
|
418
|
+
kind: "observe"
|
|
419
|
+
facts?: Record<string, unknown>
|
|
420
|
+
alerts?: CapabilityAlert[]
|
|
421
|
+
suggestedActions?: CapabilitySuggestedAction[]
|
|
422
|
+
evidence?: Record<string, unknown>
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export interface ActResult {
|
|
426
|
+
kind: "act"
|
|
427
|
+
status: "created" | "changed" | "triggered" | "skipped" | "failed"
|
|
428
|
+
changedResources?: CapabilityResourceRef[]
|
|
429
|
+
createdResources?: CapabilityResourceRef[]
|
|
430
|
+
actionResult?: Record<string, unknown>
|
|
431
|
+
evidence?: Record<string, unknown>
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export interface VerifyResult {
|
|
435
|
+
kind: "verify"
|
|
436
|
+
passed: boolean
|
|
437
|
+
evidence?: CapabilityEvidenceItem[]
|
|
438
|
+
blockers?: string[]
|
|
439
|
+
facts?: Record<string, unknown>
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export type CapabilityResult = ObserveResult | ActResult | VerifyResult
|
|
443
|
+
|
|
444
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
445
|
+
// Run-time context passed to every script.
|
|
446
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
447
|
+
|
|
448
|
+
export interface Context {
|
|
449
|
+
/** Validated CLI args, keyed by input `name`. */
|
|
450
|
+
args: Record<string, unknown>
|
|
451
|
+
/** Project root. */
|
|
452
|
+
cwd: string
|
|
453
|
+
/** Loaded kody.config.json. */
|
|
454
|
+
config: KodyConfig
|
|
455
|
+
/** Stream-output verbosity. */
|
|
456
|
+
verbose?: boolean
|
|
457
|
+
quiet?: boolean
|
|
458
|
+
/** Opaque bag scripts populate during preflight (issue, pr, diff, logs, …). */
|
|
459
|
+
data: Record<string, unknown>
|
|
460
|
+
/** Final output the executor returns. */
|
|
461
|
+
output: {
|
|
462
|
+
exitCode: number
|
|
463
|
+
prUrl?: string
|
|
464
|
+
reason?: string
|
|
465
|
+
/**
|
|
466
|
+
* In-process hand-off to the next stage. A stage (e.g. `classify`) sets
|
|
467
|
+
* this so the orchestrator runs the chosen sub-orchestrator
|
|
468
|
+
* (feature/bug/spec/chore) in the same process — instead of posting an
|
|
469
|
+
* `@kody <next>` comment, which is silently ignored when Kody comments as
|
|
470
|
+
* a GitHub App (bot author), stalling the pipeline at classify.
|
|
471
|
+
*/
|
|
472
|
+
nextDispatch?: {
|
|
473
|
+
action?: string
|
|
474
|
+
capability?: string
|
|
475
|
+
executable?: string
|
|
476
|
+
cliArgs: Record<string, unknown>
|
|
477
|
+
saveReport?: boolean
|
|
478
|
+
}
|
|
479
|
+
/** In-process hand-off to a full Job, preserving job identity in task state. */
|
|
480
|
+
nextJob?: Job
|
|
481
|
+
/** Where to return after nextJob succeeds. Used by task-jobs to keep draining pending work. */
|
|
482
|
+
afterNextJob?: {
|
|
483
|
+
action?: string
|
|
484
|
+
capability?: string
|
|
485
|
+
executable?: string
|
|
486
|
+
cliArgs: Record<string, unknown>
|
|
487
|
+
saveReport?: boolean
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* If a preflight script sets this to true, the executor skips the agent
|
|
492
|
+
* invocation and proceeds straight to postflight. Used by e.g. the
|
|
493
|
+
* clean-merge resolve path.
|
|
494
|
+
*/
|
|
495
|
+
skipAgent?: boolean
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
499
|
+
// Script signatures. Two phases, two contracts.
|
|
500
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
501
|
+
|
|
502
|
+
export type ScriptArgs = Record<string, string | number | boolean>
|
|
503
|
+
|
|
504
|
+
export type PreflightScript = (ctx: Context, profile: Profile, args?: ScriptArgs) => Promise<void>
|
|
505
|
+
|
|
506
|
+
export type PostflightScript = (
|
|
507
|
+
ctx: Context,
|
|
508
|
+
profile: Profile,
|
|
509
|
+
agentResult: AgentResult | null,
|
|
510
|
+
args?: ScriptArgs,
|
|
511
|
+
) => Promise<void>
|
|
512
|
+
|
|
513
|
+
/** A registered script may be either phase; registry looks it up by name. */
|
|
514
|
+
export type AnyScript = PreflightScript | PostflightScript
|
|
515
|
+
|
|
516
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
517
|
+
// Job — the unified work request (task-state jobs collect run attempts).
|
|
518
|
+
//
|
|
519
|
+
// A Job is the required work the engine tries to execute, regardless of how it
|
|
520
|
+
// was triggered. It must reference an capability/action capability
|
|
521
|
+
// contract. The executable is only the selected implementation detail, never a
|
|
522
|
+
// standalone request.
|
|
523
|
+
// Task state stores this durable job separately from individual run attempts.
|
|
524
|
+
// Two flavors:
|
|
525
|
+
// - "instant" — run once now (an `@kody <verb>` comment or a manual dispatch)
|
|
526
|
+
// - "scheduled" — fired on `schedule` (cron) by the tick path
|
|
527
|
+
//
|
|
528
|
+
// `runJob` (src/job.ts) lowers a Job onto the private executor after resolving
|
|
529
|
+
// the capability, and seeds both stable job metadata and per-run metadata.
|
|
530
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
531
|
+
|
|
532
|
+
export type JobFlavor = "instant" | "scheduled"
|
|
533
|
+
|
|
534
|
+
export interface Job {
|
|
535
|
+
/** Public action the user/operator invoked. Mirrors the capability action. */
|
|
536
|
+
action?: string
|
|
537
|
+
/** How: implementation profile selected by the capability. Not valid by itself. */
|
|
538
|
+
executable?: string
|
|
539
|
+
/** Why (referenced): a capability slug whose intent drives the run. */
|
|
540
|
+
capability?: string
|
|
541
|
+
/** Why (inline): free-text intent, e.g. an `@kody` comment body. Untrusted —
|
|
542
|
+
* fenced where it enters a prompt, not here. */
|
|
543
|
+
why?: string
|
|
544
|
+
/** Who: an agent identity slug. */
|
|
545
|
+
agent?: string
|
|
546
|
+
/** When: cron expression. Set for scheduled jobs, absent for instant. */
|
|
547
|
+
schedule?: string
|
|
548
|
+
/** The issue/PR number this job acts on, when applicable. */
|
|
549
|
+
target?: number
|
|
550
|
+
/** Args passed through to the executable (mirrors DispatchResult.cliArgs). */
|
|
551
|
+
cliArgs: Record<string, unknown>
|
|
552
|
+
/** Run once now ("instant") or on the schedule ("scheduled"). */
|
|
553
|
+
flavor: JobFlavor
|
|
554
|
+
/** Manual force-run (bypass cadence) for a scheduled job. */
|
|
555
|
+
force?: boolean
|
|
556
|
+
/** Ask the owning goal/loop to refresh reports/<goal-or-loop>.md after its persisted decision. */
|
|
557
|
+
saveReport?: boolean
|
|
558
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
10
|
-
"command": "node -e 'process.stderr.write(\"kody read-only mode: this
|
|
10
|
+
"command": "node -e 'process.stderr.write(\"kody read-only mode: this executable does not modify files; do not call Write/Edit/NotebookEdit\\n\");process.exit(2)'"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
package/kody.config.schema.json
CHANGED
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"enum": ["off", "low", "medium", "high"],
|
|
85
85
|
"description": "Default thinking effort for the Claude Agent SDK. Maps to maxThinkingTokens. 'off' (default) skips the thinking block entirely — no reasoning preamble, no extra tokens. 'low'/'medium'/'high' enable extended thinking with budgets 2_048/10_000/32_000. Overridable per-session via the REASONING_EFFORT env var or the dashboard's chat-level thinking dropdown."
|
|
86
86
|
},
|
|
87
|
-
"
|
|
87
|
+
"perExecutable": {
|
|
88
88
|
"type": "object",
|
|
89
|
-
"description": "Optional provider/model override by
|
|
89
|
+
"description": "Optional provider/model override by executable name.",
|
|
90
90
|
"additionalProperties": {
|
|
91
91
|
"type": "string",
|
|
92
92
|
"pattern": "^[^/]+/.+$"
|
|
@@ -120,22 +120,22 @@
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
|
-
"
|
|
123
|
+
"defaultExecutable": {
|
|
124
124
|
"type": "string",
|
|
125
|
-
"description": "
|
|
125
|
+
"description": "Executable used for bare @kody comments on issues.",
|
|
126
126
|
"default": "run"
|
|
127
127
|
},
|
|
128
|
-
"
|
|
128
|
+
"defaultPrExecutable": {
|
|
129
129
|
"type": "string",
|
|
130
|
-
"description": "Optional
|
|
130
|
+
"description": "Optional executable used for bare @kody comments on PRs. Leave unset to require explicit PR commands."
|
|
131
131
|
},
|
|
132
132
|
"onPullRequest": {
|
|
133
133
|
"type": "string",
|
|
134
|
-
"description": "Optional
|
|
134
|
+
"description": "Optional executable to run on pull_request opened, synchronize, or reopened events."
|
|
135
135
|
},
|
|
136
136
|
"aliases": {
|
|
137
137
|
"type": "object",
|
|
138
|
-
"description": "Comment subcommand aliases, mapping typed word to
|
|
138
|
+
"description": "Comment subcommand aliases, mapping typed word to executable name.",
|
|
139
139
|
"additionalProperties": {
|
|
140
140
|
"type": "string"
|
|
141
141
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative
|
|
3
|
+
"version": "0.4.262",
|
|
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",
|
|
7
7
|
"bin": {
|