@kody-ade/kody-engine 0.4.350 → 0.4.352
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 +402 -303
- package/dist/implementations/types.ts +4 -0
- package/package.json +1 -1
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.352",
|
|
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",
|
|
@@ -1983,15 +1983,19 @@ function parseWorkflowStep(value) {
|
|
|
1983
1983
|
if (!capability || !isSafeSlug(capability)) return null;
|
|
1984
1984
|
const implementation = stringField(raw.implementation);
|
|
1985
1985
|
const action = stringField(raw.action);
|
|
1986
|
+
const evidence = stringField(raw.evidence);
|
|
1986
1987
|
const agent = stringField(raw.agent);
|
|
1987
1988
|
const reason = stringField(raw.reason);
|
|
1988
1989
|
const target = stringField(raw.target);
|
|
1990
|
+
const targetFact = stringField(raw.targetFact ?? raw.target_fact);
|
|
1989
1991
|
const cliArgs = raw.cliArgs;
|
|
1990
1992
|
return {
|
|
1991
1993
|
capability,
|
|
1992
1994
|
...action && isSafeSlug(action) ? { action } : {},
|
|
1993
1995
|
...implementation && isSafeSlug(implementation) ? { implementation } : {},
|
|
1996
|
+
...evidence ? { evidence } : {},
|
|
1994
1997
|
...target === "issue" || target === "pr" ? { target } : {},
|
|
1998
|
+
...targetFact ? { targetFact } : {},
|
|
1995
1999
|
...agent && isSafeSlug(agent) ? { agent } : {},
|
|
1996
2000
|
...reason ? { reason } : {},
|
|
1997
2001
|
...cliArgs && typeof cliArgs === "object" && !Array.isArray(cliArgs) ? { cliArgs } : {},
|
|
@@ -4551,7 +4555,13 @@ function loadProfile(profilePath) {
|
|
|
4551
4555
|
const preNames = new Set(profile.scripts.preflight.map((e) => e.script).filter(Boolean));
|
|
4552
4556
|
const postNames = profile.scripts.postflight.map((e) => e.script).filter(Boolean);
|
|
4553
4557
|
const needsState = postNames.includes("writeJobStateFile") || postNames.includes("parseJobStateFromAgentResult");
|
|
4554
|
-
const STATE_LOADERS = [
|
|
4558
|
+
const STATE_LOADERS = [
|
|
4559
|
+
"loadCapabilityState",
|
|
4560
|
+
"loadJobFromFile",
|
|
4561
|
+
"runTickScript",
|
|
4562
|
+
"runScheduledImplementationTick",
|
|
4563
|
+
"runScheduledExecutableTick"
|
|
4564
|
+
];
|
|
4555
4565
|
if (needsState && !STATE_LOADERS.some((s) => preNames.has(s))) {
|
|
4556
4566
|
throw new ProfileError(
|
|
4557
4567
|
profilePath,
|
|
@@ -5769,8 +5779,10 @@ async function runContainerLoop(profile, ctx, input) {
|
|
|
5769
5779
|
const priorAction = priorState.implementations?.[child.implementation]?.lastAction;
|
|
5770
5780
|
let actionType2;
|
|
5771
5781
|
if (priorAction && /_COMPLETED$/i.test(priorAction.type)) {
|
|
5772
|
-
process.stderr.write(
|
|
5773
|
-
`)
|
|
5782
|
+
process.stderr.write(
|
|
5783
|
+
`[kody container] skipping ${child.implementation}: already completed (${priorAction.type})
|
|
5784
|
+
`
|
|
5785
|
+
);
|
|
5774
5786
|
actionType2 = priorAction.type;
|
|
5775
5787
|
} else {
|
|
5776
5788
|
let cliArgs;
|
|
@@ -7482,6 +7494,7 @@ function managedGoalFromState(state) {
|
|
|
7482
7494
|
destination: { outcome: destination.outcome, evidence },
|
|
7483
7495
|
capabilities,
|
|
7484
7496
|
route,
|
|
7497
|
+
...extra.runWithoutApproval === true ? { runWithoutApproval: true } : {},
|
|
7485
7498
|
workflowRef: asWorkflowRef(extra.workflowRef),
|
|
7486
7499
|
schedule: typeof extra.schedule === "string" ? extra.schedule : void 0,
|
|
7487
7500
|
preferredRunTime: asPreferredRunTime(extra.preferredRunTime),
|
|
@@ -7503,6 +7516,7 @@ function writeManagedGoalToState(state, goal) {
|
|
|
7503
7516
|
destination: goal.destination,
|
|
7504
7517
|
capabilities: goal.capabilities,
|
|
7505
7518
|
route: goal.route,
|
|
7519
|
+
...goal.runWithoutApproval === true ? { runWithoutApproval: true } : {},
|
|
7506
7520
|
workflowRef: goal.workflowRef,
|
|
7507
7521
|
stage: goal.stage,
|
|
7508
7522
|
facts: goal.facts,
|
|
@@ -8078,15 +8092,7 @@ function serializeTodoGoalState(goalId, state, previousRaw) {
|
|
|
8078
8092
|
const routeByEvidence = new Map(route.map((step) => [stringField3(step.evidence), step]));
|
|
8079
8093
|
const previousItems = new Map(parseItemsFromAnyRaw(previousRaw ?? "").map((item) => [item.id, item]));
|
|
8080
8094
|
const items = evidence.length > 0 ? evidence.map(
|
|
8081
|
-
(key) => itemFromEvidence(
|
|
8082
|
-
key,
|
|
8083
|
-
routeByEvidence.get(key),
|
|
8084
|
-
facts,
|
|
8085
|
-
evidenceState,
|
|
8086
|
-
createdAt,
|
|
8087
|
-
now,
|
|
8088
|
-
previousItems.get(key)
|
|
8089
|
-
)
|
|
8095
|
+
(key) => itemFromEvidence(key, routeByEvidence.get(key), facts, evidenceState, createdAt, now, previousItems.get(key))
|
|
8090
8096
|
) : stringArray(raw.capabilities).map(
|
|
8091
8097
|
(capability) => itemFromCapability(capability, createdAt, previousItems.get(capability))
|
|
8092
8098
|
);
|
|
@@ -8612,6 +8618,102 @@ var init_typeDefinitions = __esm({
|
|
|
8612
8618
|
}
|
|
8613
8619
|
});
|
|
8614
8620
|
|
|
8621
|
+
// src/workflowDefinitions.ts
|
|
8622
|
+
import * as fs28 from "fs";
|
|
8623
|
+
import * as path26 from "path";
|
|
8624
|
+
function isWorkflowDefinitionId(value) {
|
|
8625
|
+
return WORKFLOW_ID_PATTERN.test(value);
|
|
8626
|
+
}
|
|
8627
|
+
function workflowDefinitionPath(id) {
|
|
8628
|
+
if (!isWorkflowDefinitionId(id)) {
|
|
8629
|
+
throw new Error(`Invalid workflow id "${id}"`);
|
|
8630
|
+
}
|
|
8631
|
+
return `workflows/${id}/workflow.json`;
|
|
8632
|
+
}
|
|
8633
|
+
function normalizeWorkflowDefinition(value) {
|
|
8634
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
8635
|
+
const raw = value;
|
|
8636
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
8637
|
+
const workflow = parseCapabilityWorkflow({ steps: raw.steps });
|
|
8638
|
+
const steps = workflow?.steps;
|
|
8639
|
+
const capabilities = steps ? steps.map((step) => step.capability) : normalizeWorkflowCapabilities(raw.capabilities);
|
|
8640
|
+
if (!name || capabilities.length === 0) return null;
|
|
8641
|
+
return {
|
|
8642
|
+
version: 1,
|
|
8643
|
+
name,
|
|
8644
|
+
capabilities,
|
|
8645
|
+
...raw.runWithoutApproval === true ? { runWithoutApproval: true } : {},
|
|
8646
|
+
...steps ? { steps } : {},
|
|
8647
|
+
...typeof raw.createdAt === "string" ? { createdAt: raw.createdAt } : {},
|
|
8648
|
+
...typeof raw.updatedAt === "string" ? { updatedAt: raw.updatedAt } : {}
|
|
8649
|
+
};
|
|
8650
|
+
}
|
|
8651
|
+
function readWorkflowDefinition(config, cwd, id) {
|
|
8652
|
+
const file = readStateText(config, cwd, workflowDefinitionPath(id));
|
|
8653
|
+
if (!file) return readCompanyStoreWorkflowDefinition(id);
|
|
8654
|
+
return parseWorkflowDefinition(file.content);
|
|
8655
|
+
}
|
|
8656
|
+
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
8657
|
+
return {
|
|
8658
|
+
slug: id,
|
|
8659
|
+
dir: path26.dirname(source),
|
|
8660
|
+
profilePath: source,
|
|
8661
|
+
bodyPath: source,
|
|
8662
|
+
title: workflow.name,
|
|
8663
|
+
body: "",
|
|
8664
|
+
rawBody: "",
|
|
8665
|
+
rawProfile: { name: id, workflow },
|
|
8666
|
+
config: {
|
|
8667
|
+
action: id,
|
|
8668
|
+
workflow: workflowDefinitionToConfig(workflow),
|
|
8669
|
+
describe: workflow.name
|
|
8670
|
+
}
|
|
8671
|
+
};
|
|
8672
|
+
}
|
|
8673
|
+
function normalizeWorkflowCapabilities(value) {
|
|
8674
|
+
if (!Array.isArray(value)) return [];
|
|
8675
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8676
|
+
const capabilities = [];
|
|
8677
|
+
for (const item of value) {
|
|
8678
|
+
if (typeof item !== "string") continue;
|
|
8679
|
+
const slug2 = item.trim();
|
|
8680
|
+
if (!CAPABILITY_ID_PATTERN.test(slug2) || seen.has(slug2)) continue;
|
|
8681
|
+
seen.add(slug2);
|
|
8682
|
+
capabilities.push(slug2);
|
|
8683
|
+
}
|
|
8684
|
+
return capabilities;
|
|
8685
|
+
}
|
|
8686
|
+
function workflowDefinitionToConfig(workflow) {
|
|
8687
|
+
return {
|
|
8688
|
+
steps: workflow.steps ?? workflow.capabilities.map((capability) => ({ capability }))
|
|
8689
|
+
};
|
|
8690
|
+
}
|
|
8691
|
+
function readCompanyStoreWorkflowDefinition(id) {
|
|
8692
|
+
const root = getCompanyStoreAssetRoot("workflows");
|
|
8693
|
+
if (!root) return null;
|
|
8694
|
+
const filePath = path26.join(root, id, "workflow.json");
|
|
8695
|
+
if (!fs28.existsSync(filePath)) return null;
|
|
8696
|
+
return parseWorkflowDefinition(fs28.readFileSync(filePath, "utf8"));
|
|
8697
|
+
}
|
|
8698
|
+
function parseWorkflowDefinition(content) {
|
|
8699
|
+
try {
|
|
8700
|
+
return normalizeWorkflowDefinition(JSON.parse(content));
|
|
8701
|
+
} catch {
|
|
8702
|
+
return null;
|
|
8703
|
+
}
|
|
8704
|
+
}
|
|
8705
|
+
var WORKFLOW_ID_PATTERN, CAPABILITY_ID_PATTERN;
|
|
8706
|
+
var init_workflowDefinitions = __esm({
|
|
8707
|
+
"src/workflowDefinitions.ts"() {
|
|
8708
|
+
"use strict";
|
|
8709
|
+
init_capabilityFolders();
|
|
8710
|
+
init_companyStore();
|
|
8711
|
+
init_stateRepo();
|
|
8712
|
+
WORKFLOW_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
8713
|
+
CAPABILITY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$/;
|
|
8714
|
+
}
|
|
8715
|
+
});
|
|
8716
|
+
|
|
8615
8717
|
// src/scripts/issueStateComment.ts
|
|
8616
8718
|
function isStateEnvelope(x) {
|
|
8617
8719
|
if (x === null || typeof x !== "object") return false;
|
|
@@ -8796,8 +8898,8 @@ var init_contentsApiBackend = __esm({
|
|
|
8796
8898
|
});
|
|
8797
8899
|
|
|
8798
8900
|
// src/scripts/jobState/localFileBackend.ts
|
|
8799
|
-
import * as
|
|
8800
|
-
import * as
|
|
8901
|
+
import * as fs29 from "fs";
|
|
8902
|
+
import * as path27 from "path";
|
|
8801
8903
|
function sanitizeKey(s) {
|
|
8802
8904
|
return s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
8803
8905
|
}
|
|
@@ -8853,7 +8955,7 @@ var init_localFileBackend = __esm({
|
|
|
8853
8955
|
if (!opts.owner || !opts.repo) throw new Error("LocalFileBackend: owner and repo are required");
|
|
8854
8956
|
this.cwd = opts.cwd;
|
|
8855
8957
|
this.jobsDir = opts.jobsDir;
|
|
8856
|
-
this.absDir =
|
|
8958
|
+
this.absDir = path27.join(opts.cwd, opts.jobsDir);
|
|
8857
8959
|
this.owner = opts.owner;
|
|
8858
8960
|
this.repo = opts.repo;
|
|
8859
8961
|
this.cache = opts.cache ?? defaultCacheAdapter();
|
|
@@ -8868,7 +8970,7 @@ var init_localFileBackend = __esm({
|
|
|
8868
8970
|
`);
|
|
8869
8971
|
return;
|
|
8870
8972
|
}
|
|
8871
|
-
|
|
8973
|
+
fs29.mkdirSync(this.absDir, { recursive: true });
|
|
8872
8974
|
const prefix = this.cacheKeyPrefix();
|
|
8873
8975
|
const probeKey = `${prefix}probe-${Date.now()}`;
|
|
8874
8976
|
try {
|
|
@@ -8897,7 +8999,7 @@ var init_localFileBackend = __esm({
|
|
|
8897
8999
|
`);
|
|
8898
9000
|
return;
|
|
8899
9001
|
}
|
|
8900
|
-
if (!
|
|
9002
|
+
if (!fs29.existsSync(this.absDir)) {
|
|
8901
9003
|
return;
|
|
8902
9004
|
}
|
|
8903
9005
|
const key = `${this.cacheKeyPrefix()}${process.env.GITHUB_RUN_ID ?? "norunid"}-${Date.now()}`;
|
|
@@ -8913,11 +9015,11 @@ var init_localFileBackend = __esm({
|
|
|
8913
9015
|
}
|
|
8914
9016
|
load(slug2) {
|
|
8915
9017
|
const relPath = stateFilePath(this.jobsDir, slug2);
|
|
8916
|
-
const absPath =
|
|
8917
|
-
if (!
|
|
9018
|
+
const absPath = path27.join(this.cwd, relPath);
|
|
9019
|
+
if (!fs29.existsSync(absPath)) {
|
|
8918
9020
|
return { path: relPath, handle: null, state: initialStateEnvelope("seed"), created: true };
|
|
8919
9021
|
}
|
|
8920
|
-
const raw =
|
|
9022
|
+
const raw = fs29.readFileSync(absPath, "utf-8");
|
|
8921
9023
|
let parsed;
|
|
8922
9024
|
try {
|
|
8923
9025
|
parsed = JSON.parse(raw);
|
|
@@ -8934,13 +9036,13 @@ var init_localFileBackend = __esm({
|
|
|
8934
9036
|
if (!loaded.created && isStateUnchanged(loaded.state, next)) {
|
|
8935
9037
|
return false;
|
|
8936
9038
|
}
|
|
8937
|
-
const absPath =
|
|
8938
|
-
|
|
9039
|
+
const absPath = path27.join(this.cwd, loaded.path);
|
|
9040
|
+
fs29.mkdirSync(path27.dirname(absPath), { recursive: true });
|
|
8939
9041
|
const body = `${JSON.stringify(next, null, 2)}
|
|
8940
9042
|
`;
|
|
8941
9043
|
const tmpPath = `${absPath}.${process.pid}.tmp`;
|
|
8942
|
-
|
|
8943
|
-
|
|
9044
|
+
fs29.writeFileSync(tmpPath, body, "utf-8");
|
|
9045
|
+
fs29.renameSync(tmpPath, absPath);
|
|
8944
9046
|
return true;
|
|
8945
9047
|
}
|
|
8946
9048
|
cacheKeyPrefix() {
|
|
@@ -8980,7 +9082,7 @@ var init_jobState = __esm({
|
|
|
8980
9082
|
});
|
|
8981
9083
|
|
|
8982
9084
|
// src/scripts/goalCapabilityScheduling.ts
|
|
8983
|
-
import * as
|
|
9085
|
+
import * as path28 from "path";
|
|
8984
9086
|
function isCapabilityCadenceGoal(goal, extra) {
|
|
8985
9087
|
return extra.scheduleMode === "agentLoop" || extra.scheduler === "agentLoop" || goal.type === "standing" && goal.capabilities.length > 0;
|
|
8986
9088
|
}
|
|
@@ -9036,7 +9138,7 @@ function planTargetLoopSchedule(opts) {
|
|
|
9036
9138
|
}
|
|
9037
9139
|
async function planGoalCapabilitySchedule(opts) {
|
|
9038
9140
|
const jobsDir = opts.jobsDir ?? ".kody/capabilities";
|
|
9039
|
-
const jobsRoot =
|
|
9141
|
+
const jobsRoot = path28.join(opts.cwd, jobsDir);
|
|
9040
9142
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
9041
9143
|
const at = now.toISOString();
|
|
9042
9144
|
const backend = resolveBackend({ config: opts.config, cwd: opts.cwd, jobsDir });
|
|
@@ -9226,6 +9328,50 @@ var init_goalCapabilityScheduling = __esm({
|
|
|
9226
9328
|
});
|
|
9227
9329
|
|
|
9228
9330
|
// src/scripts/advanceManagedGoal.ts
|
|
9331
|
+
function scalarFacts(facts) {
|
|
9332
|
+
return Object.fromEntries(
|
|
9333
|
+
Object.entries(facts).filter(
|
|
9334
|
+
([key, value]) => key !== "pendingEvidence" && (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
9335
|
+
)
|
|
9336
|
+
);
|
|
9337
|
+
}
|
|
9338
|
+
function autonomyBlockReason(ctx, goalId, goal, dispatch2) {
|
|
9339
|
+
if (ctx.data.jobForce === true) return null;
|
|
9340
|
+
if (goal.runWithoutApproval !== true) {
|
|
9341
|
+
return `Run without approval is off for ${managedModelKind(goal)} ${goalId}`;
|
|
9342
|
+
}
|
|
9343
|
+
if (dispatch2.workflow) {
|
|
9344
|
+
const workflow = readWorkflowDefinition(ctx.config, ctx.cwd, dispatch2.workflow);
|
|
9345
|
+
if (workflow && workflow.runWithoutApproval !== true) {
|
|
9346
|
+
return `Run without approval is off for workflow ${dispatch2.workflow}`;
|
|
9347
|
+
}
|
|
9348
|
+
}
|
|
9349
|
+
const targetGoal = dispatch2.action === "goal-manager" && typeof dispatch2.cliArgs.goal === "string" ? dispatch2.cliArgs.goal : null;
|
|
9350
|
+
if (targetGoal && targetGoal !== goalId) {
|
|
9351
|
+
const target = fetchGoalState(ctx.config, targetGoal, ctx.cwd);
|
|
9352
|
+
const targetManaged = target ? managedGoalFromState(expandManagedGoalState(target)) : null;
|
|
9353
|
+
if (targetManaged && targetManaged.runWithoutApproval !== true) {
|
|
9354
|
+
return `Run without approval is off for goal ${targetGoal}`;
|
|
9355
|
+
}
|
|
9356
|
+
}
|
|
9357
|
+
return null;
|
|
9358
|
+
}
|
|
9359
|
+
function managedModelKind(goal) {
|
|
9360
|
+
return goal.loopTarget || goal.schedule ? "Loop" : "Goal";
|
|
9361
|
+
}
|
|
9362
|
+
function stageAutonomyBlocked(data, goalId, goal, goalState, reason) {
|
|
9363
|
+
stageGoalRunLogEvent(data, goalId, {
|
|
9364
|
+
source: "goal-manager",
|
|
9365
|
+
event: "goal.tick.wait",
|
|
9366
|
+
goalType: goal.type,
|
|
9367
|
+
goalState,
|
|
9368
|
+
stage: goal.stage,
|
|
9369
|
+
status: "wait",
|
|
9370
|
+
reason,
|
|
9371
|
+
goal: goalRunLogSnapshot(goalId, goalState, goal),
|
|
9372
|
+
decision: { kind: "wait", reason }
|
|
9373
|
+
});
|
|
9374
|
+
}
|
|
9229
9375
|
function stageManagedGoalDecision(data, goalId, goal, goalState, decision, details) {
|
|
9230
9376
|
if (decision.kind === "dispatch" || decision.kind === "dispatchWorkflow") {
|
|
9231
9377
|
stageGoalRunLogEvent(data, goalId, {
|
|
@@ -9400,9 +9546,11 @@ var init_advanceManagedGoal = __esm({
|
|
|
9400
9546
|
init_manager();
|
|
9401
9547
|
init_runLog();
|
|
9402
9548
|
init_state2();
|
|
9549
|
+
init_stateStore();
|
|
9403
9550
|
init_targetLoopResolution();
|
|
9404
9551
|
init_typeDefinitions();
|
|
9405
9552
|
init_issue();
|
|
9553
|
+
init_workflowDefinitions();
|
|
9406
9554
|
init_goalCapabilityScheduling();
|
|
9407
9555
|
advanceManagedGoal = async (ctx) => {
|
|
9408
9556
|
ctx.skipAgent = true;
|
|
@@ -9497,6 +9645,12 @@ var init_advanceManagedGoal = __esm({
|
|
|
9497
9645
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
9498
9646
|
goal.raw.extra.scheduleState = decision2.scheduleState;
|
|
9499
9647
|
ctx.data.managedGoalDecision = decision2;
|
|
9648
|
+
const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, decision2.dispatch) : null;
|
|
9649
|
+
if (autonomyBlock) {
|
|
9650
|
+
stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
|
|
9651
|
+
ctx.output.reason = autonomyBlock;
|
|
9652
|
+
return;
|
|
9653
|
+
}
|
|
9500
9654
|
if (decision2.kind === "dispatch" && decision2.dispatch) {
|
|
9501
9655
|
ctx.output.nextDispatch = {
|
|
9502
9656
|
...decision2.dispatch.action ? { action: decision2.dispatch.action } : {},
|
|
@@ -9553,6 +9707,12 @@ var init_advanceManagedGoal = __esm({
|
|
|
9553
9707
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
9554
9708
|
goal.raw.extra.scheduleState = decision2.scheduleState;
|
|
9555
9709
|
ctx.data.managedGoalDecision = decision2;
|
|
9710
|
+
const autonomyBlock = decision2.kind === "dispatch" && decision2.dispatch ? autonomyBlockReason(ctx, goal.id, managed, decision2.dispatch) : null;
|
|
9711
|
+
if (autonomyBlock) {
|
|
9712
|
+
stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
|
|
9713
|
+
ctx.output.reason = autonomyBlock;
|
|
9714
|
+
return;
|
|
9715
|
+
}
|
|
9556
9716
|
if (decision2.kind === "dispatch" && decision2.dispatch) {
|
|
9557
9717
|
ctx.output.nextDispatch = {
|
|
9558
9718
|
capability: decision2.dispatch.capability,
|
|
@@ -9606,6 +9766,19 @@ var init_advanceManagedGoal = __esm({
|
|
|
9606
9766
|
}
|
|
9607
9767
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
9608
9768
|
const afterDecisionSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
9769
|
+
if (decision.kind === "dispatch" || decision.kind === "dispatchWorkflow") {
|
|
9770
|
+
const planned = decision.kind === "dispatchWorkflow" ? { workflow: decision.workflow, cliArgs: decision.cliArgs } : {
|
|
9771
|
+
capability: decision.capability,
|
|
9772
|
+
...decision.implementation ? { implementation: decision.implementation } : {},
|
|
9773
|
+
cliArgs: decision.cliArgs
|
|
9774
|
+
};
|
|
9775
|
+
const autonomyBlock = autonomyBlockReason(ctx, goal.id, managed, planned);
|
|
9776
|
+
if (autonomyBlock) {
|
|
9777
|
+
stageAutonomyBlocked(ctx.data, goal.id, managed, goal.state, autonomyBlock);
|
|
9778
|
+
ctx.output.reason = autonomyBlock;
|
|
9779
|
+
return;
|
|
9780
|
+
}
|
|
9781
|
+
}
|
|
9609
9782
|
stageManagedGoalDecision(ctx.data, goal.id, managed, goal.state, decision, {
|
|
9610
9783
|
goalSnapshot: afterDecisionSnapshot,
|
|
9611
9784
|
inspection: {
|
|
@@ -9626,8 +9799,9 @@ var init_advanceManagedGoal = __esm({
|
|
|
9626
9799
|
ctx.output.nextDispatch = {
|
|
9627
9800
|
workflow: decision.workflow,
|
|
9628
9801
|
cliArgs: decision.cliArgs,
|
|
9802
|
+
workflowFacts: scalarFacts(managed.facts),
|
|
9629
9803
|
...decision.saveReport === true ? { saveReport: true } : {},
|
|
9630
|
-
resultTarget: { type: "goal", id: goal.id }
|
|
9804
|
+
resultTarget: { type: "goal", id: goal.id, evidence: decision.evidence }
|
|
9631
9805
|
};
|
|
9632
9806
|
ctx.output.reason = `dispatch workflow ${decision.workflow} for ${decision.evidence}`;
|
|
9633
9807
|
return;
|
|
@@ -11145,8 +11319,8 @@ var init_classifyByLabel = __esm({
|
|
|
11145
11319
|
});
|
|
11146
11320
|
|
|
11147
11321
|
// src/scripts/commitAndPush.ts
|
|
11148
|
-
import * as
|
|
11149
|
-
import * as
|
|
11322
|
+
import * as fs30 from "fs";
|
|
11323
|
+
import * as path29 from "path";
|
|
11150
11324
|
function sentinelPathForStage(cwd, profileName) {
|
|
11151
11325
|
const runId = resolveRunId();
|
|
11152
11326
|
return runtimeStatePath(cwd, "agent-runs", runId, `commit-${profileName}.lock`);
|
|
@@ -11167,9 +11341,9 @@ var init_commitAndPush = __esm({
|
|
|
11167
11341
|
}
|
|
11168
11342
|
const idempotencyEnabled = process.env.KODY_COMMIT_IDEMPOTENCY !== "0";
|
|
11169
11343
|
const sentinel = idempotencyEnabled ? sentinelPathForStage(ctx.cwd, profile.name) : null;
|
|
11170
|
-
if (sentinel &&
|
|
11344
|
+
if (sentinel && fs30.existsSync(sentinel)) {
|
|
11171
11345
|
try {
|
|
11172
|
-
const replay = JSON.parse(
|
|
11346
|
+
const replay = JSON.parse(fs30.readFileSync(sentinel, "utf-8"));
|
|
11173
11347
|
ctx.data.commitResult = replay.commitResult ?? { committed: false, pushed: false };
|
|
11174
11348
|
if (Array.isArray(replay.changedFiles)) ctx.data.changedFiles = replay.changedFiles;
|
|
11175
11349
|
if (typeof replay.hasCommitsAhead === "boolean") ctx.data.hasCommitsAhead = replay.hasCommitsAhead;
|
|
@@ -11222,8 +11396,8 @@ var init_commitAndPush = __esm({
|
|
|
11222
11396
|
const result = ctx.data.commitResult;
|
|
11223
11397
|
if (sentinel && result?.committed) {
|
|
11224
11398
|
try {
|
|
11225
|
-
|
|
11226
|
-
|
|
11399
|
+
fs30.mkdirSync(path29.dirname(sentinel), { recursive: true });
|
|
11400
|
+
fs30.writeFileSync(
|
|
11227
11401
|
sentinel,
|
|
11228
11402
|
JSON.stringify(
|
|
11229
11403
|
{
|
|
@@ -11314,8 +11488,8 @@ var init_commitGoalState = __esm({
|
|
|
11314
11488
|
});
|
|
11315
11489
|
|
|
11316
11490
|
// src/scripts/composePrompt.ts
|
|
11317
|
-
import * as
|
|
11318
|
-
import * as
|
|
11491
|
+
import * as fs31 from "fs";
|
|
11492
|
+
import * as path30 from "path";
|
|
11319
11493
|
function fenceUntrusted(value) {
|
|
11320
11494
|
if (value.trim().length === 0) return value;
|
|
11321
11495
|
const safe = value.replace(/-{3,}\s*END UNTRUSTED INPUT\s*-{3,}/gi, "[END UNTRUSTED INPUT]");
|
|
@@ -11436,10 +11610,10 @@ var init_composePrompt = __esm({
|
|
|
11436
11610
|
const explicit = ctx.data.promptTemplate;
|
|
11437
11611
|
const mode = ctx.args.mode;
|
|
11438
11612
|
const candidates = [
|
|
11439
|
-
explicit ?
|
|
11440
|
-
mode ?
|
|
11441
|
-
|
|
11442
|
-
|
|
11613
|
+
explicit ? path30.join(profile.dir, explicit) : null,
|
|
11614
|
+
mode ? path30.join(profile.dir, "prompts", `${mode}.md`) : null,
|
|
11615
|
+
path30.join(profile.dir, "prompt.md"),
|
|
11616
|
+
path30.join(profile.dir, "capability.md")
|
|
11443
11617
|
].filter(Boolean);
|
|
11444
11618
|
let templatePath = "";
|
|
11445
11619
|
let template = "";
|
|
@@ -11452,7 +11626,7 @@ var init_composePrompt = __esm({
|
|
|
11452
11626
|
break;
|
|
11453
11627
|
}
|
|
11454
11628
|
try {
|
|
11455
|
-
template =
|
|
11629
|
+
template = fs31.readFileSync(c, "utf-8");
|
|
11456
11630
|
templatePath = c;
|
|
11457
11631
|
break;
|
|
11458
11632
|
} catch (err) {
|
|
@@ -11463,7 +11637,7 @@ var init_composePrompt = __esm({
|
|
|
11463
11637
|
if (!templatePath) {
|
|
11464
11638
|
let dirState;
|
|
11465
11639
|
try {
|
|
11466
|
-
dirState = `dir contents: [${
|
|
11640
|
+
dirState = `dir contents: [${fs31.readdirSync(profile.dir).join(", ")}]`;
|
|
11467
11641
|
} catch (err) {
|
|
11468
11642
|
dirState = `readdir(${profile.dir}) failed: ${err?.code ?? String(err)}`;
|
|
11469
11643
|
}
|
|
@@ -12152,19 +12326,19 @@ var init_deriveQaScopeFromIssue = __esm({
|
|
|
12152
12326
|
|
|
12153
12327
|
// src/scripts/diagMcp.ts
|
|
12154
12328
|
import { execFileSync as execFileSync10 } from "child_process";
|
|
12155
|
-
import * as
|
|
12329
|
+
import * as fs32 from "fs";
|
|
12156
12330
|
import * as os6 from "os";
|
|
12157
|
-
import * as
|
|
12331
|
+
import * as path31 from "path";
|
|
12158
12332
|
var diagMcp;
|
|
12159
12333
|
var init_diagMcp = __esm({
|
|
12160
12334
|
"src/scripts/diagMcp.ts"() {
|
|
12161
12335
|
"use strict";
|
|
12162
12336
|
diagMcp = async (_ctx) => {
|
|
12163
12337
|
const home = os6.homedir();
|
|
12164
|
-
const cacheDir =
|
|
12338
|
+
const cacheDir = path31.join(home, ".cache", "ms-playwright");
|
|
12165
12339
|
let entries = [];
|
|
12166
12340
|
try {
|
|
12167
|
-
entries =
|
|
12341
|
+
entries = fs32.readdirSync(cacheDir);
|
|
12168
12342
|
} catch {
|
|
12169
12343
|
}
|
|
12170
12344
|
const hasChromium = entries.some((e) => e.startsWith("chromium"));
|
|
@@ -12192,13 +12366,13 @@ var init_diagMcp = __esm({
|
|
|
12192
12366
|
});
|
|
12193
12367
|
|
|
12194
12368
|
// src/scripts/frameworkDetectors.ts
|
|
12195
|
-
import * as
|
|
12196
|
-
import * as
|
|
12369
|
+
import * as fs33 from "fs";
|
|
12370
|
+
import * as path32 from "path";
|
|
12197
12371
|
function detectFrameworks(cwd) {
|
|
12198
12372
|
const out = [];
|
|
12199
12373
|
let deps = {};
|
|
12200
12374
|
try {
|
|
12201
|
-
const pkg = JSON.parse(
|
|
12375
|
+
const pkg = JSON.parse(fs33.readFileSync(path32.join(cwd, "package.json"), "utf-8"));
|
|
12202
12376
|
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12203
12377
|
} catch {
|
|
12204
12378
|
return out;
|
|
@@ -12235,25 +12409,25 @@ function detectFrameworks(cwd) {
|
|
|
12235
12409
|
}
|
|
12236
12410
|
function findFile(cwd, candidates) {
|
|
12237
12411
|
for (const c of candidates) {
|
|
12238
|
-
if (
|
|
12412
|
+
if (fs33.existsSync(path32.join(cwd, c))) return c;
|
|
12239
12413
|
}
|
|
12240
12414
|
return null;
|
|
12241
12415
|
}
|
|
12242
12416
|
function discoverPayloadCollections(cwd) {
|
|
12243
12417
|
const out = [];
|
|
12244
12418
|
for (const dir of COLLECTION_DIRS) {
|
|
12245
|
-
const full =
|
|
12246
|
-
if (!
|
|
12419
|
+
const full = path32.join(cwd, dir);
|
|
12420
|
+
if (!fs33.existsSync(full)) continue;
|
|
12247
12421
|
let files;
|
|
12248
12422
|
try {
|
|
12249
|
-
files =
|
|
12423
|
+
files = fs33.readdirSync(full).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
12250
12424
|
} catch {
|
|
12251
12425
|
continue;
|
|
12252
12426
|
}
|
|
12253
12427
|
for (const file of files) {
|
|
12254
12428
|
try {
|
|
12255
|
-
const filePath =
|
|
12256
|
-
const content =
|
|
12429
|
+
const filePath = path32.join(full, file);
|
|
12430
|
+
const content = fs33.readFileSync(filePath, "utf-8").slice(0, 1e4);
|
|
12257
12431
|
const slugMatch = content.match(/slug:\s*['"]([a-z0-9-]+)['"]/);
|
|
12258
12432
|
if (!slugMatch) continue;
|
|
12259
12433
|
const slug2 = slugMatch[1];
|
|
@@ -12267,7 +12441,7 @@ function discoverPayloadCollections(cwd) {
|
|
|
12267
12441
|
out.push({
|
|
12268
12442
|
name,
|
|
12269
12443
|
slug: slug2,
|
|
12270
|
-
filePath:
|
|
12444
|
+
filePath: path32.relative(cwd, filePath),
|
|
12271
12445
|
fields: fields.slice(0, 20),
|
|
12272
12446
|
hasAdmin
|
|
12273
12447
|
});
|
|
@@ -12280,28 +12454,28 @@ function discoverPayloadCollections(cwd) {
|
|
|
12280
12454
|
function discoverAdminComponents(cwd, collections) {
|
|
12281
12455
|
const out = [];
|
|
12282
12456
|
for (const dir of ADMIN_COMPONENT_DIRS) {
|
|
12283
|
-
const full =
|
|
12284
|
-
if (!
|
|
12457
|
+
const full = path32.join(cwd, dir);
|
|
12458
|
+
if (!fs33.existsSync(full)) continue;
|
|
12285
12459
|
let entries;
|
|
12286
12460
|
try {
|
|
12287
|
-
entries =
|
|
12461
|
+
entries = fs33.readdirSync(full, { withFileTypes: true });
|
|
12288
12462
|
} catch {
|
|
12289
12463
|
continue;
|
|
12290
12464
|
}
|
|
12291
12465
|
for (const entry of entries) {
|
|
12292
|
-
const entryPath =
|
|
12466
|
+
const entryPath = path32.join(full, entry.name);
|
|
12293
12467
|
let name;
|
|
12294
12468
|
let filePath;
|
|
12295
12469
|
if (entry.isDirectory()) {
|
|
12296
12470
|
const indexFile = ["index.tsx", "index.ts", "index.jsx", "index.js"].find(
|
|
12297
|
-
(f) =>
|
|
12471
|
+
(f) => fs33.existsSync(path32.join(entryPath, f))
|
|
12298
12472
|
);
|
|
12299
12473
|
if (!indexFile) continue;
|
|
12300
12474
|
name = entry.name;
|
|
12301
|
-
filePath =
|
|
12475
|
+
filePath = path32.relative(cwd, path32.join(entryPath, indexFile));
|
|
12302
12476
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
12303
12477
|
name = entry.name.replace(/\.(tsx?|jsx?)$/, "");
|
|
12304
|
-
filePath =
|
|
12478
|
+
filePath = path32.relative(cwd, entryPath);
|
|
12305
12479
|
} else {
|
|
12306
12480
|
continue;
|
|
12307
12481
|
}
|
|
@@ -12309,7 +12483,7 @@ function discoverAdminComponents(cwd, collections) {
|
|
|
12309
12483
|
if (collections) {
|
|
12310
12484
|
for (const col of collections) {
|
|
12311
12485
|
try {
|
|
12312
|
-
const colContent =
|
|
12486
|
+
const colContent = fs33.readFileSync(path32.join(cwd, col.filePath), "utf-8");
|
|
12313
12487
|
if (colContent.includes(name)) {
|
|
12314
12488
|
usedInCollection = col.slug;
|
|
12315
12489
|
break;
|
|
@@ -12327,8 +12501,8 @@ function scanApiRoutes(cwd) {
|
|
|
12327
12501
|
const out = [];
|
|
12328
12502
|
const appDirs = ["src/app", "app"];
|
|
12329
12503
|
for (const appDir of appDirs) {
|
|
12330
|
-
const apiDir =
|
|
12331
|
-
if (!
|
|
12504
|
+
const apiDir = path32.join(cwd, appDir, "api");
|
|
12505
|
+
if (!fs33.existsSync(apiDir)) continue;
|
|
12332
12506
|
walkApiRoutes(apiDir, "/api", cwd, out);
|
|
12333
12507
|
break;
|
|
12334
12508
|
}
|
|
@@ -12337,14 +12511,14 @@ function scanApiRoutes(cwd) {
|
|
|
12337
12511
|
function walkApiRoutes(dir, prefix, cwd, out) {
|
|
12338
12512
|
let entries;
|
|
12339
12513
|
try {
|
|
12340
|
-
entries =
|
|
12514
|
+
entries = fs33.readdirSync(dir, { withFileTypes: true });
|
|
12341
12515
|
} catch {
|
|
12342
12516
|
return;
|
|
12343
12517
|
}
|
|
12344
12518
|
const routeFile = entries.find((e) => e.isFile() && /^route\.(ts|js|tsx|jsx)$/.test(e.name));
|
|
12345
12519
|
if (routeFile) {
|
|
12346
12520
|
try {
|
|
12347
|
-
const content =
|
|
12521
|
+
const content = fs33.readFileSync(path32.join(dir, routeFile.name), "utf-8").slice(0, 5e3);
|
|
12348
12522
|
const methods = HTTP_METHODS.filter(
|
|
12349
12523
|
(m) => new RegExp(`export\\s+(?:async\\s+)?function\\s+${m}\\b`).test(content)
|
|
12350
12524
|
);
|
|
@@ -12352,7 +12526,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12352
12526
|
out.push({
|
|
12353
12527
|
path: prefix,
|
|
12354
12528
|
methods,
|
|
12355
|
-
filePath:
|
|
12529
|
+
filePath: path32.relative(cwd, path32.join(dir, routeFile.name))
|
|
12356
12530
|
});
|
|
12357
12531
|
}
|
|
12358
12532
|
} catch {
|
|
@@ -12363,7 +12537,7 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12363
12537
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
12364
12538
|
let segment = entry.name;
|
|
12365
12539
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
12366
|
-
walkApiRoutes(
|
|
12540
|
+
walkApiRoutes(path32.join(dir, entry.name), prefix, cwd, out);
|
|
12367
12541
|
continue;
|
|
12368
12542
|
}
|
|
12369
12543
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -12371,16 +12545,16 @@ function walkApiRoutes(dir, prefix, cwd, out) {
|
|
|
12371
12545
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
12372
12546
|
segment = `:${segment.slice(1, -1)}`;
|
|
12373
12547
|
}
|
|
12374
|
-
walkApiRoutes(
|
|
12548
|
+
walkApiRoutes(path32.join(dir, entry.name), `${prefix}/${segment}`, cwd, out);
|
|
12375
12549
|
}
|
|
12376
12550
|
}
|
|
12377
12551
|
function scanEnvVars(cwd) {
|
|
12378
12552
|
const candidates = [".env.example", ".env.local.example", ".env.template"];
|
|
12379
12553
|
for (const envFile of candidates) {
|
|
12380
|
-
const envPath =
|
|
12381
|
-
if (!
|
|
12554
|
+
const envPath = path32.join(cwd, envFile);
|
|
12555
|
+
if (!fs33.existsSync(envPath)) continue;
|
|
12382
12556
|
try {
|
|
12383
|
-
const content =
|
|
12557
|
+
const content = fs33.readFileSync(envPath, "utf-8");
|
|
12384
12558
|
const vars = [];
|
|
12385
12559
|
for (const line of content.split("\n")) {
|
|
12386
12560
|
const trimmed = line.trim();
|
|
@@ -12425,8 +12599,8 @@ var init_frameworkDetectors = __esm({
|
|
|
12425
12599
|
});
|
|
12426
12600
|
|
|
12427
12601
|
// src/scripts/discoverQaContext.ts
|
|
12428
|
-
import * as
|
|
12429
|
-
import * as
|
|
12602
|
+
import * as fs34 from "fs";
|
|
12603
|
+
import * as path33 from "path";
|
|
12430
12604
|
function runQaDiscovery(cwd) {
|
|
12431
12605
|
const out = {
|
|
12432
12606
|
routes: [],
|
|
@@ -12457,9 +12631,9 @@ function runQaDiscovery(cwd) {
|
|
|
12457
12631
|
}
|
|
12458
12632
|
function detectDevServer(cwd, out) {
|
|
12459
12633
|
try {
|
|
12460
|
-
const pkg = JSON.parse(
|
|
12634
|
+
const pkg = JSON.parse(fs34.readFileSync(path33.join(cwd, "package.json"), "utf-8"));
|
|
12461
12635
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
12462
|
-
const pm =
|
|
12636
|
+
const pm = fs34.existsSync(path33.join(cwd, "pnpm-lock.yaml")) ? "pnpm" : fs34.existsSync(path33.join(cwd, "yarn.lock")) ? "yarn" : fs34.existsSync(path33.join(cwd, "bun.lockb")) ? "bun" : "npm";
|
|
12463
12637
|
if (pkg.scripts?.dev) out.devCommand = `${pm} dev`;
|
|
12464
12638
|
if (allDeps.next || allDeps.nuxt) out.devPort = 3e3;
|
|
12465
12639
|
else if (allDeps.vite) out.devPort = 5173;
|
|
@@ -12469,8 +12643,8 @@ function detectDevServer(cwd, out) {
|
|
|
12469
12643
|
function scanFrontendRoutes(cwd, out) {
|
|
12470
12644
|
const appDirs = ["src/app", "app"];
|
|
12471
12645
|
for (const appDir of appDirs) {
|
|
12472
|
-
const full =
|
|
12473
|
-
if (!
|
|
12646
|
+
const full = path33.join(cwd, appDir);
|
|
12647
|
+
if (!fs34.existsSync(full)) continue;
|
|
12474
12648
|
walkFrontendRoutes(full, "", out);
|
|
12475
12649
|
break;
|
|
12476
12650
|
}
|
|
@@ -12478,7 +12652,7 @@ function scanFrontendRoutes(cwd, out) {
|
|
|
12478
12652
|
function walkFrontendRoutes(dir, prefix, out) {
|
|
12479
12653
|
let entries;
|
|
12480
12654
|
try {
|
|
12481
|
-
entries =
|
|
12655
|
+
entries = fs34.readdirSync(dir, { withFileTypes: true });
|
|
12482
12656
|
} catch {
|
|
12483
12657
|
return;
|
|
12484
12658
|
}
|
|
@@ -12495,7 +12669,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
12495
12669
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
12496
12670
|
let segment = entry.name;
|
|
12497
12671
|
if (segment.startsWith("(") && segment.endsWith(")")) {
|
|
12498
|
-
walkFrontendRoutes(
|
|
12672
|
+
walkFrontendRoutes(path33.join(dir, entry.name), prefix, out);
|
|
12499
12673
|
continue;
|
|
12500
12674
|
}
|
|
12501
12675
|
if (segment.startsWith("[[") && segment.endsWith("]]")) {
|
|
@@ -12503,7 +12677,7 @@ function walkFrontendRoutes(dir, prefix, out) {
|
|
|
12503
12677
|
} else if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
12504
12678
|
segment = `:${segment.slice(1, -1)}`;
|
|
12505
12679
|
}
|
|
12506
|
-
walkFrontendRoutes(
|
|
12680
|
+
walkFrontendRoutes(path33.join(dir, entry.name), `${prefix}/${segment}`, out);
|
|
12507
12681
|
}
|
|
12508
12682
|
}
|
|
12509
12683
|
function detectAuthFiles(cwd, out) {
|
|
@@ -12520,23 +12694,23 @@ function detectAuthFiles(cwd, out) {
|
|
|
12520
12694
|
"src/app/api/oauth"
|
|
12521
12695
|
];
|
|
12522
12696
|
for (const c of candidates) {
|
|
12523
|
-
if (
|
|
12697
|
+
if (fs34.existsSync(path33.join(cwd, c))) out.authFiles.push(c);
|
|
12524
12698
|
}
|
|
12525
12699
|
}
|
|
12526
12700
|
function detectRoles(cwd, out) {
|
|
12527
12701
|
const rolePaths = ["src/types", "src/lib", "src/utils", "src/constants", "src/access", "src/collections"];
|
|
12528
12702
|
for (const rp of rolePaths) {
|
|
12529
|
-
const dir =
|
|
12530
|
-
if (!
|
|
12703
|
+
const dir = path33.join(cwd, rp);
|
|
12704
|
+
if (!fs34.existsSync(dir)) continue;
|
|
12531
12705
|
let files;
|
|
12532
12706
|
try {
|
|
12533
|
-
files =
|
|
12707
|
+
files = fs34.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx"));
|
|
12534
12708
|
} catch {
|
|
12535
12709
|
continue;
|
|
12536
12710
|
}
|
|
12537
12711
|
for (const f of files) {
|
|
12538
12712
|
try {
|
|
12539
|
-
const content =
|
|
12713
|
+
const content = fs34.readFileSync(path33.join(dir, f), "utf-8").slice(0, 5e3);
|
|
12540
12714
|
const roleMatches = content.match(/(?:role|Role|ROLE)\s*[=:]\s*['"](\w+)['"]/g);
|
|
12541
12715
|
if (roleMatches) {
|
|
12542
12716
|
for (const m of roleMatches) {
|
|
@@ -13781,12 +13955,12 @@ var init_fixFlow = __esm({
|
|
|
13781
13955
|
|
|
13782
13956
|
// src/scripts/initFlow.ts
|
|
13783
13957
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
13784
|
-
import * as
|
|
13785
|
-
import * as
|
|
13958
|
+
import * as fs35 from "fs";
|
|
13959
|
+
import * as path34 from "path";
|
|
13786
13960
|
function detectPackageManager(cwd) {
|
|
13787
|
-
if (
|
|
13788
|
-
if (
|
|
13789
|
-
if (
|
|
13961
|
+
if (fs35.existsSync(path34.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
13962
|
+
if (fs35.existsSync(path34.join(cwd, "yarn.lock"))) return "yarn";
|
|
13963
|
+
if (fs35.existsSync(path34.join(cwd, "bun.lockb"))) return "bun";
|
|
13790
13964
|
return "npm";
|
|
13791
13965
|
}
|
|
13792
13966
|
function qualityCommandsFor(pm) {
|
|
@@ -13858,22 +14032,22 @@ function performInit(cwd, force) {
|
|
|
13858
14032
|
const pm = detectPackageManager(cwd);
|
|
13859
14033
|
const ownerRepo = detectOwnerRepo(cwd);
|
|
13860
14034
|
const defaultBranch = defaultBranchFromGit(cwd);
|
|
13861
|
-
const configPath =
|
|
13862
|
-
if (
|
|
14035
|
+
const configPath = path34.join(cwd, "kody.config.json");
|
|
14036
|
+
if (fs35.existsSync(configPath) && !force) {
|
|
13863
14037
|
skipped.push("kody.config.json");
|
|
13864
14038
|
} else {
|
|
13865
14039
|
const cfg = makeConfig(pm, ownerRepo, defaultBranch);
|
|
13866
|
-
|
|
14040
|
+
fs35.writeFileSync(configPath, `${JSON.stringify(cfg, null, 2)}
|
|
13867
14041
|
`);
|
|
13868
14042
|
wrote.push("kody.config.json");
|
|
13869
14043
|
}
|
|
13870
|
-
const workflowDir =
|
|
13871
|
-
const workflowPath =
|
|
13872
|
-
if (
|
|
14044
|
+
const workflowDir = path34.join(cwd, ".github", "workflows");
|
|
14045
|
+
const workflowPath = path34.join(workflowDir, "kody.yml");
|
|
14046
|
+
if (fs35.existsSync(workflowPath) && !force) {
|
|
13873
14047
|
skipped.push(".github/workflows/kody.yml");
|
|
13874
14048
|
} else {
|
|
13875
|
-
|
|
13876
|
-
|
|
14049
|
+
fs35.mkdirSync(workflowDir, { recursive: true });
|
|
14050
|
+
fs35.writeFileSync(workflowPath, WORKFLOW_TEMPLATE);
|
|
13877
14051
|
wrote.push(".github/workflows/kody.yml");
|
|
13878
14052
|
}
|
|
13879
14053
|
for (const exe of listImplementations()) {
|
|
@@ -13884,12 +14058,12 @@ function performInit(cwd, force) {
|
|
|
13884
14058
|
continue;
|
|
13885
14059
|
}
|
|
13886
14060
|
if (profile.kind !== "scheduled" || !profile.schedule) continue;
|
|
13887
|
-
const target =
|
|
13888
|
-
if (
|
|
14061
|
+
const target = path34.join(workflowDir, `kody-${exe.name}.yml`);
|
|
14062
|
+
if (fs35.existsSync(target) && !force) {
|
|
13889
14063
|
skipped.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
13890
14064
|
continue;
|
|
13891
14065
|
}
|
|
13892
|
-
|
|
14066
|
+
fs35.writeFileSync(target, renderScheduledWorkflow(exe.name, profile.schedule));
|
|
13893
14067
|
wrote.push(`.github/workflows/kody-${exe.name}.yml`);
|
|
13894
14068
|
}
|
|
13895
14069
|
let labels;
|
|
@@ -14037,7 +14211,7 @@ Nothing to do. All files already present. (Use --force to overwrite.)
|
|
|
14037
14211
|
});
|
|
14038
14212
|
|
|
14039
14213
|
// src/scripts/loadAgentAdhoc.ts
|
|
14040
|
-
import * as
|
|
14214
|
+
import * as fs36 from "fs";
|
|
14041
14215
|
function resolveMessage(messageArg) {
|
|
14042
14216
|
const fromComment = readCommentBody();
|
|
14043
14217
|
if (fromComment) return stripDirective(fromComment);
|
|
@@ -14045,9 +14219,9 @@ function resolveMessage(messageArg) {
|
|
|
14045
14219
|
}
|
|
14046
14220
|
function readCommentBody() {
|
|
14047
14221
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
14048
|
-
if (!eventPath || !
|
|
14222
|
+
if (!eventPath || !fs36.existsSync(eventPath)) return "";
|
|
14049
14223
|
try {
|
|
14050
|
-
const event = JSON.parse(
|
|
14224
|
+
const event = JSON.parse(fs36.readFileSync(eventPath, "utf-8"));
|
|
14051
14225
|
return String(event.comment?.body ?? "");
|
|
14052
14226
|
} catch {
|
|
14053
14227
|
return "";
|
|
@@ -14100,10 +14274,10 @@ var init_loadAgentAdhoc = __esm({
|
|
|
14100
14274
|
throw new Error("loadAgentAdhoc: ctx.args.agent must be a non-empty slug");
|
|
14101
14275
|
}
|
|
14102
14276
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14103
|
-
if (!
|
|
14277
|
+
if (!fs36.existsSync(agentPath)) {
|
|
14104
14278
|
throw new Error(`loadAgentAdhoc: agent identity not found: ${agentPath}`);
|
|
14105
14279
|
}
|
|
14106
|
-
const { title, body } = parseAgentFile(
|
|
14280
|
+
const { title, body } = parseAgentFile(fs36.readFileSync(agentPath, "utf-8"), agentSlug);
|
|
14107
14281
|
const message = resolveMessage(ctx.args.message);
|
|
14108
14282
|
if (!message) {
|
|
14109
14283
|
throw new Error(
|
|
@@ -14347,8 +14521,8 @@ var init_loadIssueStateComment = __esm({
|
|
|
14347
14521
|
});
|
|
14348
14522
|
|
|
14349
14523
|
// src/scripts/loadJobFromFile.ts
|
|
14350
|
-
import * as
|
|
14351
|
-
import * as
|
|
14524
|
+
import * as fs37 from "fs";
|
|
14525
|
+
import * as path35 from "path";
|
|
14352
14526
|
function parseJobFile(raw, slug2) {
|
|
14353
14527
|
let stripped = raw;
|
|
14354
14528
|
if (stripped.startsWith("---\n")) {
|
|
@@ -14386,9 +14560,9 @@ var init_loadJobFromFile = __esm({
|
|
|
14386
14560
|
if (!slug2) {
|
|
14387
14561
|
throw new Error(`loadJobFromFile: ctx.args.${slugArg} must be a non-empty slug`);
|
|
14388
14562
|
}
|
|
14389
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
14563
|
+
const capability = resolveCapabilityFolder(slug2, path35.join(ctx.cwd, jobsDir));
|
|
14390
14564
|
if (!capability) {
|
|
14391
|
-
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${
|
|
14565
|
+
throw new Error(`loadJobFromFile: capability folder not found or incomplete: ${path35.join(ctx.cwd, jobsDir, slug2)}`);
|
|
14392
14566
|
}
|
|
14393
14567
|
const { title, body, config } = capability;
|
|
14394
14568
|
const mentions = (config.mentions ?? []).map((login) => `@${login}`).join(" ");
|
|
@@ -14397,12 +14571,12 @@ var init_loadJobFromFile = __esm({
|
|
|
14397
14571
|
let agentIdentity = "";
|
|
14398
14572
|
if (agentSlug) {
|
|
14399
14573
|
const agentPath = resolveAgentFile(ctx.cwd, agentSlug, agentsDir);
|
|
14400
|
-
if (!
|
|
14574
|
+
if (!fs37.existsSync(agentPath)) {
|
|
14401
14575
|
throw new Error(
|
|
14402
14576
|
`loadJobFromFile: capability '${slug2}' declares agent '${agentSlug}' but ${agentPath} does not exist`
|
|
14403
14577
|
);
|
|
14404
14578
|
}
|
|
14405
|
-
const agentRaw =
|
|
14579
|
+
const agentRaw = fs37.readFileSync(agentPath, "utf-8");
|
|
14406
14580
|
const parsed = parseJobFile(agentRaw, agentSlug);
|
|
14407
14581
|
agentTitle = parsed.title;
|
|
14408
14582
|
agentIdentity = parsed.body;
|
|
@@ -14482,13 +14656,13 @@ ${truncate(issue.body, FINDING_BODY_MAX_BYTES)}`;
|
|
|
14482
14656
|
});
|
|
14483
14657
|
|
|
14484
14658
|
// src/scripts/kodyVariables.ts
|
|
14485
|
-
import * as
|
|
14486
|
-
import * as
|
|
14659
|
+
import * as fs38 from "fs";
|
|
14660
|
+
import * as path36 from "path";
|
|
14487
14661
|
function readKodyVariables(cwd) {
|
|
14488
|
-
const full =
|
|
14662
|
+
const full = path36.join(cwd, KODY_VARIABLES_REL_PATH);
|
|
14489
14663
|
let raw;
|
|
14490
14664
|
try {
|
|
14491
|
-
raw =
|
|
14665
|
+
raw = fs38.readFileSync(full, "utf-8");
|
|
14492
14666
|
} catch {
|
|
14493
14667
|
return {};
|
|
14494
14668
|
}
|
|
@@ -14556,8 +14730,8 @@ var init_keys = __esm({
|
|
|
14556
14730
|
});
|
|
14557
14731
|
|
|
14558
14732
|
// src/stateRepoGithub.ts
|
|
14559
|
-
import * as
|
|
14560
|
-
import * as
|
|
14733
|
+
import * as fs39 from "fs";
|
|
14734
|
+
import * as path37 from "path";
|
|
14561
14735
|
function recordValue4(value) {
|
|
14562
14736
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14563
14737
|
}
|
|
@@ -14697,15 +14871,15 @@ function mergeJsonl(localText, remoteText) {
|
|
|
14697
14871
|
async function syncJsonlFileFromGithubState(opts) {
|
|
14698
14872
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
14699
14873
|
if (!remote) return;
|
|
14700
|
-
const local =
|
|
14874
|
+
const local = fs39.existsSync(opts.localPath) ? fs39.readFileSync(opts.localPath, "utf-8") : "";
|
|
14701
14875
|
const next = mergeJsonl(local, remote.content);
|
|
14702
14876
|
if (next === local) return;
|
|
14703
|
-
|
|
14704
|
-
|
|
14877
|
+
fs39.mkdirSync(path37.dirname(opts.localPath), { recursive: true });
|
|
14878
|
+
fs39.writeFileSync(opts.localPath, next);
|
|
14705
14879
|
}
|
|
14706
14880
|
async function persistJsonlFileToGithubState(opts) {
|
|
14707
|
-
if (!
|
|
14708
|
-
const localText =
|
|
14881
|
+
if (!fs39.existsSync(opts.localPath)) return;
|
|
14882
|
+
const localText = fs39.readFileSync(opts.localPath, "utf-8");
|
|
14709
14883
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
14710
14884
|
const remote = await readGithubStateTextWithConfig(opts);
|
|
14711
14885
|
const body = mergeJsonl(localText, remote?.content ?? "");
|
|
@@ -14844,8 +15018,8 @@ var init_runtimeSecrets = __esm({
|
|
|
14844
15018
|
});
|
|
14845
15019
|
|
|
14846
15020
|
// src/scripts/loadQaContext.ts
|
|
14847
|
-
import * as
|
|
14848
|
-
import * as
|
|
15021
|
+
import * as fs40 from "fs";
|
|
15022
|
+
import * as path38 from "path";
|
|
14849
15023
|
function parseSlugList(value) {
|
|
14850
15024
|
const inner = value.startsWith("[") && value.endsWith("]") ? value.slice(1, -1) : value;
|
|
14851
15025
|
return inner.split(",").map(
|
|
@@ -14874,18 +15048,18 @@ function readProfileAgents(raw) {
|
|
|
14874
15048
|
return { agent: agent ?? legacy ?? ["kody"], body };
|
|
14875
15049
|
}
|
|
14876
15050
|
function readProfile(cwd) {
|
|
14877
|
-
const dir =
|
|
14878
|
-
if (!
|
|
15051
|
+
const dir = path38.join(cwd, CONTEXT_DIR_REL_PATH);
|
|
15052
|
+
if (!fs40.existsSync(dir)) return "";
|
|
14879
15053
|
let entries;
|
|
14880
15054
|
try {
|
|
14881
|
-
entries =
|
|
15055
|
+
entries = fs40.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
14882
15056
|
} catch {
|
|
14883
15057
|
return "";
|
|
14884
15058
|
}
|
|
14885
15059
|
const blocks = [];
|
|
14886
15060
|
for (const file of entries) {
|
|
14887
15061
|
try {
|
|
14888
|
-
const raw =
|
|
15062
|
+
const raw = fs40.readFileSync(path38.join(dir, file), "utf-8");
|
|
14889
15063
|
const { agent, body } = readProfileAgents(raw);
|
|
14890
15064
|
if (!agent.includes(QA_AGENT) && !agent.includes(ALL_AGENTS)) continue;
|
|
14891
15065
|
blocks.push(`## ${file}
|
|
@@ -14934,8 +15108,8 @@ var init_loadQaContext = __esm({
|
|
|
14934
15108
|
});
|
|
14935
15109
|
|
|
14936
15110
|
// src/taskContext.ts
|
|
14937
|
-
import * as
|
|
14938
|
-
import * as
|
|
15111
|
+
import * as fs41 from "fs";
|
|
15112
|
+
import * as path39 from "path";
|
|
14939
15113
|
function buildTaskContext(args) {
|
|
14940
15114
|
return {
|
|
14941
15115
|
schemaVersion: TASK_CONTEXT_SCHEMA_VERSION,
|
|
@@ -14951,9 +15125,9 @@ function buildTaskContext(args) {
|
|
|
14951
15125
|
function persistTaskContext(cwd, ctx) {
|
|
14952
15126
|
try {
|
|
14953
15127
|
const dir = runtimeStatePath(cwd, "agent-runs", ctx.runId);
|
|
14954
|
-
|
|
14955
|
-
const file =
|
|
14956
|
-
|
|
15128
|
+
fs41.mkdirSync(dir, { recursive: true });
|
|
15129
|
+
const file = path39.join(dir, "task-context.json");
|
|
15130
|
+
fs41.writeFileSync(file, `${JSON.stringify(ctx, null, 2)}
|
|
14957
15131
|
`);
|
|
14958
15132
|
return file;
|
|
14959
15133
|
} catch (err) {
|
|
@@ -17463,12 +17637,12 @@ fi
|
|
|
17463
17637
|
|
|
17464
17638
|
// src/scripts/runPreviewBuild.ts
|
|
17465
17639
|
import { copyFile, writeFile } from "fs/promises";
|
|
17466
|
-
import * as
|
|
17640
|
+
import * as path40 from "path";
|
|
17467
17641
|
import { fileURLToPath } from "url";
|
|
17468
17642
|
function bundledDockerfilePath(mode) {
|
|
17469
|
-
const here =
|
|
17643
|
+
const here = path40.dirname(fileURLToPath(import.meta.url));
|
|
17470
17644
|
const file = mode === "dev" ? "default-Dockerfile.preview.dev" : "default-Dockerfile.preview.prod";
|
|
17471
|
-
return
|
|
17645
|
+
return path40.join(here, "preview-build-templates", file);
|
|
17472
17646
|
}
|
|
17473
17647
|
function required(name) {
|
|
17474
17648
|
const v = (process.env[name] ?? "").trim();
|
|
@@ -17719,10 +17893,10 @@ var init_runPreviewBuild = __esm({
|
|
|
17719
17893
|
console.log(`[preview-build] vault: ${Object.keys(buildEnv).length} secrets, mode=${buildMode}`);
|
|
17720
17894
|
if (Object.keys(buildEnv).length > 0) {
|
|
17721
17895
|
const lines = Object.entries(buildEnv).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
|
|
17722
|
-
await writeFile(
|
|
17896
|
+
await writeFile(path40.join(ctx.cwd, ".env.production.local"), `${lines.join("\n")}
|
|
17723
17897
|
`, "utf8");
|
|
17724
17898
|
}
|
|
17725
|
-
const consumerDockerfile =
|
|
17899
|
+
const consumerDockerfile = path40.join(ctx.cwd, "Dockerfile.preview");
|
|
17726
17900
|
const { stat } = await import("fs/promises");
|
|
17727
17901
|
let hasConsumerDockerfile = false;
|
|
17728
17902
|
try {
|
|
@@ -17906,8 +18080,8 @@ var init_tickShellRunner = __esm({
|
|
|
17906
18080
|
});
|
|
17907
18081
|
|
|
17908
18082
|
// src/scripts/runScheduledImplementationTick.ts
|
|
17909
|
-
import * as
|
|
17910
|
-
import * as
|
|
18083
|
+
import * as fs42 from "fs";
|
|
18084
|
+
import * as path41 from "path";
|
|
17911
18085
|
var runScheduledImplementationTick;
|
|
17912
18086
|
var init_runScheduledImplementationTick = __esm({
|
|
17913
18087
|
"src/scripts/runScheduledImplementationTick.ts"() {
|
|
@@ -17927,14 +18101,14 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
17927
18101
|
ctx.output.reason = `runScheduledImplementationTick: args.slug or ctx.args.${slugArg} must be non-empty capability slug`;
|
|
17928
18102
|
return;
|
|
17929
18103
|
}
|
|
17930
|
-
const capability = resolveCapabilityFolder(slug2,
|
|
18104
|
+
const capability = resolveCapabilityFolder(slug2, path41.join(ctx.cwd, jobsDir));
|
|
17931
18105
|
if (!capability) {
|
|
17932
18106
|
ctx.output.exitCode = 99;
|
|
17933
18107
|
ctx.output.reason = `runScheduledImplementationTick: capability folder not found or incomplete: ${slug2} (searched ${jobsDir} and company store)`;
|
|
17934
18108
|
return;
|
|
17935
18109
|
}
|
|
17936
|
-
const shellPath =
|
|
17937
|
-
if (!
|
|
18110
|
+
const shellPath = path41.join(profile.dir, shell);
|
|
18111
|
+
if (!fs42.existsSync(shellPath)) {
|
|
17938
18112
|
ctx.output.exitCode = 99;
|
|
17939
18113
|
ctx.output.reason = `runScheduledImplementationTick: shell not found: ${shell} (looked in ${profile.dir})`;
|
|
17940
18114
|
return;
|
|
@@ -17965,8 +18139,8 @@ var init_runScheduledImplementationTick = __esm({
|
|
|
17965
18139
|
});
|
|
17966
18140
|
|
|
17967
18141
|
// src/scripts/runTickScript.ts
|
|
17968
|
-
import * as
|
|
17969
|
-
import * as
|
|
18142
|
+
import * as fs43 from "fs";
|
|
18143
|
+
import * as path42 from "path";
|
|
17970
18144
|
var runTickScript;
|
|
17971
18145
|
var init_runTickScript = __esm({
|
|
17972
18146
|
"src/scripts/runTickScript.ts"() {
|
|
@@ -17985,10 +18159,10 @@ var init_runTickScript = __esm({
|
|
|
17985
18159
|
ctx.output.reason = `runTickScript: ctx.args.${slugArg} must be a non-empty slug`;
|
|
17986
18160
|
return;
|
|
17987
18161
|
}
|
|
17988
|
-
const capability = readCapabilityFolder(
|
|
18162
|
+
const capability = readCapabilityFolder(path42.join(ctx.cwd, jobsDir), slug2);
|
|
17989
18163
|
if (!capability) {
|
|
17990
18164
|
ctx.output.exitCode = 99;
|
|
17991
|
-
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${
|
|
18165
|
+
ctx.output.reason = `runTickScript: capability folder not found or incomplete: ${path42.join(ctx.cwd, jobsDir, slug2)}`;
|
|
17992
18166
|
return;
|
|
17993
18167
|
}
|
|
17994
18168
|
const tickScript = capability.config.tickScript;
|
|
@@ -17997,8 +18171,8 @@ var init_runTickScript = __esm({
|
|
|
17997
18171
|
ctx.output.reason = `runTickScript: capability ${slug2} has no \`tickScript\` in profile.json \u2014 route via capability-tick instead`;
|
|
17998
18172
|
return;
|
|
17999
18173
|
}
|
|
18000
|
-
const scriptPath =
|
|
18001
|
-
if (!
|
|
18174
|
+
const scriptPath = path42.isAbsolute(tickScript) ? tickScript : path42.join(ctx.cwd, tickScript);
|
|
18175
|
+
if (!fs43.existsSync(scriptPath)) {
|
|
18002
18176
|
ctx.output.exitCode = 99;
|
|
18003
18177
|
ctx.output.reason = `runTickScript: tickScript not found: ${scriptPath}`;
|
|
18004
18178
|
return;
|
|
@@ -19143,7 +19317,7 @@ var init_warmupMcp = __esm({
|
|
|
19143
19317
|
});
|
|
19144
19318
|
|
|
19145
19319
|
// src/scripts/writeAgentRunSummary.ts
|
|
19146
|
-
import * as
|
|
19320
|
+
import * as fs44 from "fs";
|
|
19147
19321
|
var writeAgentRunSummary;
|
|
19148
19322
|
var init_writeAgentRunSummary = __esm({
|
|
19149
19323
|
"src/scripts/writeAgentRunSummary.ts"() {
|
|
@@ -19169,7 +19343,7 @@ var init_writeAgentRunSummary = __esm({
|
|
|
19169
19343
|
if (reason) lines.push(`- **Reason:** ${reason}`);
|
|
19170
19344
|
lines.push("");
|
|
19171
19345
|
try {
|
|
19172
|
-
|
|
19346
|
+
fs44.appendFileSync(summaryPath, `${lines.join("\n")}
|
|
19173
19347
|
`);
|
|
19174
19348
|
} catch {
|
|
19175
19349
|
}
|
|
@@ -19427,6 +19601,7 @@ var init_scripts = __esm({
|
|
|
19427
19601
|
planTaskJobs,
|
|
19428
19602
|
dispatchNextTaskJob,
|
|
19429
19603
|
runScheduledImplementationTick,
|
|
19604
|
+
runScheduledExecutableTick: runScheduledImplementationTick,
|
|
19430
19605
|
runTickScript,
|
|
19431
19606
|
runPreviewBuild,
|
|
19432
19607
|
advanceManagedGoal,
|
|
@@ -19495,53 +19670,53 @@ var init_scripts = __esm({
|
|
|
19495
19670
|
// src/stateWorkspace.ts
|
|
19496
19671
|
import { execFileSync as execFileSync24 } from "child_process";
|
|
19497
19672
|
import * as crypto3 from "crypto";
|
|
19498
|
-
import * as
|
|
19673
|
+
import * as fs45 from "fs";
|
|
19499
19674
|
import * as os7 from "os";
|
|
19500
|
-
import * as
|
|
19675
|
+
import * as path43 from "path";
|
|
19501
19676
|
function writeLocalFile(cwd, relativePath, content) {
|
|
19502
|
-
const fullPath =
|
|
19503
|
-
|
|
19504
|
-
|
|
19677
|
+
const fullPath = path43.join(cwd, relativePath);
|
|
19678
|
+
fs45.mkdirSync(path43.dirname(fullPath), { recursive: true });
|
|
19679
|
+
fs45.writeFileSync(fullPath, content);
|
|
19505
19680
|
}
|
|
19506
19681
|
function copyPath(source, target) {
|
|
19507
|
-
const st =
|
|
19508
|
-
|
|
19682
|
+
const st = fs45.lstatSync(source);
|
|
19683
|
+
fs45.rmSync(target, { recursive: true, force: true });
|
|
19509
19684
|
if (st.isSymbolicLink()) return;
|
|
19510
|
-
|
|
19511
|
-
|
|
19685
|
+
fs45.mkdirSync(path43.dirname(target), { recursive: true });
|
|
19686
|
+
fs45.cpSync(source, target, { recursive: true, force: true });
|
|
19512
19687
|
}
|
|
19513
19688
|
function overlayDirectoryChildren(cwd, sourceDir, localDir) {
|
|
19514
|
-
if (!
|
|
19515
|
-
for (const entry of
|
|
19516
|
-
const source =
|
|
19517
|
-
const target =
|
|
19689
|
+
if (!fs45.existsSync(sourceDir)) return;
|
|
19690
|
+
for (const entry of fs45.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
19691
|
+
const source = path43.join(sourceDir, entry.name);
|
|
19692
|
+
const target = path43.join(cwd, localDir, entry.name);
|
|
19518
19693
|
copyPath(source, target);
|
|
19519
19694
|
}
|
|
19520
19695
|
}
|
|
19521
19696
|
function hydrateStateWorkspace(config, cwd) {
|
|
19522
19697
|
if (process.env.VITEST && process.env[TEST_FETCH_ENV] !== "1") return;
|
|
19523
19698
|
const parsed = parseStateRepo(config);
|
|
19524
|
-
const hydrateKey = `${
|
|
19699
|
+
const hydrateKey = `${path43.resolve(cwd)}|${parsed.owner}/${parsed.repo}|${parsed.basePath}|${parsed.branch}`;
|
|
19525
19700
|
if (hydratedWorkspaces.has(hydrateKey)) return;
|
|
19526
19701
|
const snapshotRoot = fetchStateSnapshot(parsed);
|
|
19527
19702
|
for (const mapping of DIR_MAPPINGS) {
|
|
19528
|
-
overlayDirectoryChildren(cwd,
|
|
19703
|
+
overlayDirectoryChildren(cwd, path43.join(snapshotRoot, mapping.stateDir), mapping.localDir);
|
|
19529
19704
|
}
|
|
19530
19705
|
for (const mapping of FILE_MAPPINGS) {
|
|
19531
|
-
const source =
|
|
19532
|
-
if (
|
|
19533
|
-
writeLocalFile(cwd, mapping.localPath,
|
|
19706
|
+
const source = path43.join(snapshotRoot, mapping.statePath);
|
|
19707
|
+
if (fs45.existsSync(source) && !fs45.lstatSync(source).isSymbolicLink() && fs45.statSync(source).isFile()) {
|
|
19708
|
+
writeLocalFile(cwd, mapping.localPath, fs45.readFileSync(source, "utf-8"));
|
|
19534
19709
|
}
|
|
19535
19710
|
}
|
|
19536
19711
|
hydratedWorkspaces.add(hydrateKey);
|
|
19537
19712
|
}
|
|
19538
19713
|
function fetchStateSnapshot(parsed) {
|
|
19539
|
-
const cacheDir =
|
|
19714
|
+
const cacheDir = path43.join(cacheRoot2(), cacheKey3(parsed));
|
|
19540
19715
|
const url = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
19541
19716
|
try {
|
|
19542
|
-
|
|
19543
|
-
if (!
|
|
19544
|
-
|
|
19717
|
+
fs45.mkdirSync(path43.dirname(cacheDir), { recursive: true });
|
|
19718
|
+
if (!fs45.existsSync(path43.join(cacheDir, ".git"))) {
|
|
19719
|
+
fs45.rmSync(cacheDir, { recursive: true, force: true });
|
|
19545
19720
|
runGit3(["clone", "--no-checkout", "--filter=blob:none", url, cacheDir]);
|
|
19546
19721
|
}
|
|
19547
19722
|
runGit3(["-C", cacheDir, "remote", "set-url", "origin", url]);
|
|
@@ -19556,10 +19731,10 @@ function fetchStateSnapshot(parsed) {
|
|
|
19556
19731
|
`stateWorkspace: failed to fetch ${parsed.owner}/${parsed.repo}:${parsed.basePath}@${parsed.branch}: ${msg}`
|
|
19557
19732
|
);
|
|
19558
19733
|
}
|
|
19559
|
-
return
|
|
19734
|
+
return path43.join(cacheDir, parsed.basePath);
|
|
19560
19735
|
}
|
|
19561
19736
|
function cacheRoot2() {
|
|
19562
|
-
return process.env[CACHE_ENV2]?.trim() ||
|
|
19737
|
+
return process.env[CACHE_ENV2]?.trim() || path43.join(os7.homedir(), ".cache", "kody", "state-repo");
|
|
19563
19738
|
}
|
|
19564
19739
|
function cacheKey3(parsed) {
|
|
19565
19740
|
return crypto3.createHash("sha256").update(`${parsed.owner}/${parsed.repo}#${parsed.branch}#${parsed.basePath}`).digest("hex").slice(0, 24);
|
|
@@ -19599,15 +19774,15 @@ var init_stateWorkspace = __esm({
|
|
|
19599
19774
|
"use strict";
|
|
19600
19775
|
init_stateRepo();
|
|
19601
19776
|
DIR_MAPPINGS = [
|
|
19602
|
-
{ stateDir: "capabilities", localDir:
|
|
19603
|
-
{ stateDir: "agents", localDir:
|
|
19604
|
-
{ stateDir: "context", localDir:
|
|
19605
|
-
{ stateDir: "memory", localDir:
|
|
19777
|
+
{ stateDir: "capabilities", localDir: path43.join(".kody", "capabilities") },
|
|
19778
|
+
{ stateDir: "agents", localDir: path43.join(".kody", "agents") },
|
|
19779
|
+
{ stateDir: "context", localDir: path43.join(".kody", "context") },
|
|
19780
|
+
{ stateDir: "memory", localDir: path43.join(".kody", "memory") }
|
|
19606
19781
|
];
|
|
19607
19782
|
FILE_MAPPINGS = [
|
|
19608
|
-
{ statePath: "instructions.md", localPath:
|
|
19609
|
-
{ statePath: "variables.json", localPath:
|
|
19610
|
-
{ statePath: "secrets.enc", localPath:
|
|
19783
|
+
{ statePath: "instructions.md", localPath: path43.join(".kody", "instructions.md") },
|
|
19784
|
+
{ statePath: "variables.json", localPath: path43.join(".kody", "variables.json") },
|
|
19785
|
+
{ statePath: "secrets.enc", localPath: path43.join(".kody", "secrets.enc") }
|
|
19611
19786
|
];
|
|
19612
19787
|
CACHE_ENV2 = "KODY_STATE_REPO_CACHE";
|
|
19613
19788
|
TEST_FETCH_ENV = "KODY_STATE_WORKSPACE_FETCH_FOR_TESTS";
|
|
@@ -19681,8 +19856,8 @@ var init_tools = __esm({
|
|
|
19681
19856
|
|
|
19682
19857
|
// src/executor.ts
|
|
19683
19858
|
import { spawn as spawn7 } from "child_process";
|
|
19684
|
-
import * as
|
|
19685
|
-
import * as
|
|
19859
|
+
import * as fs46 from "fs";
|
|
19860
|
+
import * as path44 from "path";
|
|
19686
19861
|
function isMutatingPostflight(scriptName) {
|
|
19687
19862
|
return MUTATING_POSTFLIGHTS.has(scriptName ?? "");
|
|
19688
19863
|
}
|
|
@@ -19727,9 +19902,7 @@ function jobReferenceBlock(profileName, profile, data) {
|
|
|
19727
19902
|
const jobId = typeof data.jobId === "string" && data.jobId.length > 0 ? data.jobId : null;
|
|
19728
19903
|
const flavor = typeof data.jobFlavor === "string" && data.jobFlavor.length > 0 ? data.jobFlavor : null;
|
|
19729
19904
|
const schedule = typeof data.jobSchedule === "string" && data.jobSchedule.length > 0 ? data.jobSchedule : null;
|
|
19730
|
-
const isJob2 = Boolean(
|
|
19731
|
-
jobId || flavor || schedule || data.jobCapability || data.selectedImplementation || data.jobWhy
|
|
19732
|
-
);
|
|
19905
|
+
const isJob2 = Boolean(jobId || flavor || schedule || data.jobCapability || data.selectedImplementation || data.jobWhy);
|
|
19733
19906
|
if (!isJob2) return null;
|
|
19734
19907
|
const capability = typeof data.jobCapability === "string" && data.jobCapability.length > 0 ? data.jobCapability : profile.implementation ? profile.name : null;
|
|
19735
19908
|
const implementation = typeof profile.implementation === "string" && profile.implementation.length > 0 ? profile.implementation : typeof data.selectedImplementation === "string" && data.selectedImplementation.length > 0 ? data.selectedImplementation : profileName;
|
|
@@ -19907,7 +20080,7 @@ async function runImplementation(profileName, input) {
|
|
|
19907
20080
|
const jobWhyBlock = typeof ctx.data.jobWhy === "string" ? operatorRequestBlock(ctx.data.jobWhy) : null;
|
|
19908
20081
|
const jobRefBlock = jobReferenceBlock(profileName, profile, ctx.data);
|
|
19909
20082
|
const invokeAgent = async (prompt) => {
|
|
19910
|
-
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) =>
|
|
20083
|
+
const externalPlugins = (profile.claudeCode.plugins ?? []).map((p) => path44.isAbsolute(p) ? p : path44.resolve(profile.dir, p)).filter((p) => p.length > 0);
|
|
19911
20084
|
const syntheticPath = ctx.data.syntheticPluginPath;
|
|
19912
20085
|
const pluginPaths = [...externalPlugins, ...syntheticPath ? [syntheticPath] : []];
|
|
19913
20086
|
const agents = loadSubagents(profile);
|
|
@@ -20309,6 +20482,7 @@ function handoffToJob(handoff) {
|
|
|
20309
20482
|
workflow: handoff.workflow,
|
|
20310
20483
|
implementation: handoff.implementation,
|
|
20311
20484
|
cliArgs: handoff.cliArgs,
|
|
20485
|
+
workflowFacts: handoff.workflowFacts,
|
|
20312
20486
|
flavor: "instant",
|
|
20313
20487
|
saveReport: handoff.saveReport === true,
|
|
20314
20488
|
resultTarget: handoff.resultTarget
|
|
@@ -20333,17 +20507,17 @@ function clearStampedLifecycleLabels(profile, ctx) {
|
|
|
20333
20507
|
function resolveProfilePath(profileName) {
|
|
20334
20508
|
const found = resolveImplementation(profileName);
|
|
20335
20509
|
if (found) return found;
|
|
20336
|
-
const here =
|
|
20510
|
+
const here = path44.dirname(new URL(import.meta.url).pathname);
|
|
20337
20511
|
const candidates = [
|
|
20338
|
-
|
|
20512
|
+
path44.join(here, "implementations", profileName, "profile.json"),
|
|
20339
20513
|
// same-dir sibling (dev)
|
|
20340
|
-
|
|
20514
|
+
path44.join(here, "..", "implementations", profileName, "profile.json"),
|
|
20341
20515
|
// up one (prod: dist/bin → dist/implementations)
|
|
20342
|
-
|
|
20516
|
+
path44.join(here, "..", "src", "implementations", profileName, "profile.json")
|
|
20343
20517
|
// fallback
|
|
20344
20518
|
];
|
|
20345
20519
|
for (const c of candidates) {
|
|
20346
|
-
if (
|
|
20520
|
+
if (fs46.existsSync(c)) return c;
|
|
20347
20521
|
}
|
|
20348
20522
|
return candidates[0];
|
|
20349
20523
|
}
|
|
@@ -20458,8 +20632,8 @@ function resolveShellTimeoutMs(entry) {
|
|
|
20458
20632
|
}
|
|
20459
20633
|
async function runShellEntry(entry, ctx, profile) {
|
|
20460
20634
|
const shellName = entry.shell;
|
|
20461
|
-
const shellPath =
|
|
20462
|
-
if (!
|
|
20635
|
+
const shellPath = path44.join(profile.dir, shellName);
|
|
20636
|
+
if (!fs46.existsSync(shellPath)) {
|
|
20463
20637
|
ctx.skipAgent = true;
|
|
20464
20638
|
ctx.output.exitCode = 99;
|
|
20465
20639
|
ctx.output.reason = `shell script not found: ${shellName} (looked in ${profile.dir})`;
|
|
@@ -20610,101 +20784,6 @@ var init_executor = __esm({
|
|
|
20610
20784
|
}
|
|
20611
20785
|
});
|
|
20612
20786
|
|
|
20613
|
-
// src/workflowDefinitions.ts
|
|
20614
|
-
import * as fs46 from "fs";
|
|
20615
|
-
import * as path44 from "path";
|
|
20616
|
-
function isWorkflowDefinitionId(value) {
|
|
20617
|
-
return WORKFLOW_ID_PATTERN.test(value);
|
|
20618
|
-
}
|
|
20619
|
-
function workflowDefinitionPath(id) {
|
|
20620
|
-
if (!isWorkflowDefinitionId(id)) {
|
|
20621
|
-
throw new Error(`Invalid workflow id "${id}"`);
|
|
20622
|
-
}
|
|
20623
|
-
return `workflows/${id}/workflow.json`;
|
|
20624
|
-
}
|
|
20625
|
-
function normalizeWorkflowDefinition(value) {
|
|
20626
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
20627
|
-
const raw = value;
|
|
20628
|
-
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
20629
|
-
const workflow = parseCapabilityWorkflow({ steps: raw.steps });
|
|
20630
|
-
const steps = workflow?.steps;
|
|
20631
|
-
const capabilities = steps ? steps.map((step) => step.capability) : normalizeWorkflowCapabilities(raw.capabilities);
|
|
20632
|
-
if (!name || capabilities.length === 0) return null;
|
|
20633
|
-
return {
|
|
20634
|
-
version: 1,
|
|
20635
|
-
name,
|
|
20636
|
-
capabilities,
|
|
20637
|
-
...steps ? { steps } : {},
|
|
20638
|
-
...typeof raw.createdAt === "string" ? { createdAt: raw.createdAt } : {},
|
|
20639
|
-
...typeof raw.updatedAt === "string" ? { updatedAt: raw.updatedAt } : {}
|
|
20640
|
-
};
|
|
20641
|
-
}
|
|
20642
|
-
function readWorkflowDefinition(config, cwd, id) {
|
|
20643
|
-
const file = readStateText(config, cwd, workflowDefinitionPath(id));
|
|
20644
|
-
if (!file) return readCompanyStoreWorkflowDefinition(id);
|
|
20645
|
-
return parseWorkflowDefinition(file.content);
|
|
20646
|
-
}
|
|
20647
|
-
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
20648
|
-
return {
|
|
20649
|
-
slug: id,
|
|
20650
|
-
dir: path44.dirname(source),
|
|
20651
|
-
profilePath: source,
|
|
20652
|
-
bodyPath: source,
|
|
20653
|
-
title: workflow.name,
|
|
20654
|
-
body: "",
|
|
20655
|
-
rawBody: "",
|
|
20656
|
-
rawProfile: { name: id, workflow },
|
|
20657
|
-
config: {
|
|
20658
|
-
action: id,
|
|
20659
|
-
workflow: workflowDefinitionToConfig(workflow),
|
|
20660
|
-
describe: workflow.name
|
|
20661
|
-
}
|
|
20662
|
-
};
|
|
20663
|
-
}
|
|
20664
|
-
function normalizeWorkflowCapabilities(value) {
|
|
20665
|
-
if (!Array.isArray(value)) return [];
|
|
20666
|
-
const seen = /* @__PURE__ */ new Set();
|
|
20667
|
-
const capabilities = [];
|
|
20668
|
-
for (const item of value) {
|
|
20669
|
-
if (typeof item !== "string") continue;
|
|
20670
|
-
const slug2 = item.trim();
|
|
20671
|
-
if (!CAPABILITY_ID_PATTERN.test(slug2) || seen.has(slug2)) continue;
|
|
20672
|
-
seen.add(slug2);
|
|
20673
|
-
capabilities.push(slug2);
|
|
20674
|
-
}
|
|
20675
|
-
return capabilities;
|
|
20676
|
-
}
|
|
20677
|
-
function workflowDefinitionToConfig(workflow) {
|
|
20678
|
-
return {
|
|
20679
|
-
steps: workflow.steps ?? workflow.capabilities.map((capability) => ({ capability }))
|
|
20680
|
-
};
|
|
20681
|
-
}
|
|
20682
|
-
function readCompanyStoreWorkflowDefinition(id) {
|
|
20683
|
-
const root = getCompanyStoreAssetRoot("workflows");
|
|
20684
|
-
if (!root) return null;
|
|
20685
|
-
const filePath = path44.join(root, id, "workflow.json");
|
|
20686
|
-
if (!fs46.existsSync(filePath)) return null;
|
|
20687
|
-
return parseWorkflowDefinition(fs46.readFileSync(filePath, "utf8"));
|
|
20688
|
-
}
|
|
20689
|
-
function parseWorkflowDefinition(content) {
|
|
20690
|
-
try {
|
|
20691
|
-
return normalizeWorkflowDefinition(JSON.parse(content));
|
|
20692
|
-
} catch {
|
|
20693
|
-
return null;
|
|
20694
|
-
}
|
|
20695
|
-
}
|
|
20696
|
-
var WORKFLOW_ID_PATTERN, CAPABILITY_ID_PATTERN;
|
|
20697
|
-
var init_workflowDefinitions = __esm({
|
|
20698
|
-
"src/workflowDefinitions.ts"() {
|
|
20699
|
-
"use strict";
|
|
20700
|
-
init_capabilityFolders();
|
|
20701
|
-
init_companyStore();
|
|
20702
|
-
init_stateRepo();
|
|
20703
|
-
WORKFLOW_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
20704
|
-
CAPABILITY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$/;
|
|
20705
|
-
}
|
|
20706
|
-
});
|
|
20707
|
-
|
|
20708
20787
|
// src/job.ts
|
|
20709
20788
|
var job_exports = {};
|
|
20710
20789
|
__export(job_exports, {
|
|
@@ -20748,6 +20827,7 @@ function validateJob(input) {
|
|
|
20748
20827
|
schedule: typeof j.schedule === "string" ? j.schedule : void 0,
|
|
20749
20828
|
target: typeof j.target === "number" ? j.target : void 0,
|
|
20750
20829
|
cliArgs: j.cliArgs ?? {},
|
|
20830
|
+
workflowFacts: j.workflowFacts && typeof j.workflowFacts === "object" && !Array.isArray(j.workflowFacts) ? j.workflowFacts : void 0,
|
|
20751
20831
|
flavor: j.flavor,
|
|
20752
20832
|
force: j.force === true,
|
|
20753
20833
|
saveReport: j.saveReport === true,
|
|
@@ -20824,6 +20904,7 @@ async function runCapabilityImplementationStep(valid, profileName, capabilityIde
|
|
|
20824
20904
|
preloadedData.selectedImplementation = profileName;
|
|
20825
20905
|
if (valid.schedule !== void 0 && valid.schedule.length > 0) preloadedData.jobSchedule = valid.schedule;
|
|
20826
20906
|
if (valid.saveReport === true) preloadedData.jobSaveReport = true;
|
|
20907
|
+
if (valid.force === true) preloadedData.jobForce = true;
|
|
20827
20908
|
if (valid.resultTarget) preloadedData.capabilityResultTarget = valid.resultTarget;
|
|
20828
20909
|
if (capabilityContext) {
|
|
20829
20910
|
preloadedData.capabilitySlug = capabilityContext.slug;
|
|
@@ -20876,13 +20957,15 @@ async function runCapabilityWorkflow(parent, workflow, capability, base) {
|
|
|
20876
20957
|
workflowTitle: capability.title,
|
|
20877
20958
|
workflowStepCount: workflow.steps.length,
|
|
20878
20959
|
workflowIssueNumber: workflowIssueNumber(parent),
|
|
20960
|
+
workflowFacts: parent.workflowFacts ?? {},
|
|
20879
20961
|
workflowStack: [
|
|
20880
20962
|
...Array.isArray(base.preloadedData?.workflowStack) ? base.preloadedData.workflowStack.filter((entry) => typeof entry === "string") : [],
|
|
20881
20963
|
capability.slug
|
|
20882
20964
|
]
|
|
20883
20965
|
};
|
|
20884
20966
|
let result = { exitCode: 0 };
|
|
20885
|
-
|
|
20967
|
+
const startIndex = workflowResumeStartIndex(workflow.steps, parent.resultTarget?.evidence);
|
|
20968
|
+
for (let index = startIndex; index < workflow.steps.length; index++) {
|
|
20886
20969
|
const step = workflow.steps[index];
|
|
20887
20970
|
const label = step.action ?? step.capability;
|
|
20888
20971
|
if (!shouldRunWorkflowStep(step, chainData)) {
|
|
@@ -21014,10 +21097,23 @@ function valueMatches(actual, expected) {
|
|
|
21014
21097
|
return actual === expected;
|
|
21015
21098
|
}
|
|
21016
21099
|
function workflowStepTargetNumber(step, parent, chainData) {
|
|
21017
|
-
if (step.target === "pr")
|
|
21100
|
+
if (step.target === "pr")
|
|
21101
|
+
return workflowPrNumber(chainData) ?? workflowTargetFactNumber(step, chainData) ?? targetFromCliArgs(step.cliArgs ?? {});
|
|
21018
21102
|
if (step.target === "issue") return workflowIssueNumber(parent);
|
|
21019
21103
|
return typeof parent.target === "number" ? parent.target : targetFromCliArgs({ ...parent.cliArgs, ...step.cliArgs ?? {} });
|
|
21020
21104
|
}
|
|
21105
|
+
function workflowResumeStartIndex(steps, evidence) {
|
|
21106
|
+
if (!evidence) return 0;
|
|
21107
|
+
const index = steps.findIndex((step) => step.evidence === evidence);
|
|
21108
|
+
return index >= 0 ? index : 0;
|
|
21109
|
+
}
|
|
21110
|
+
function workflowTargetFactNumber(step, data) {
|
|
21111
|
+
if (!step.targetFact) return void 0;
|
|
21112
|
+
const facts = data.workflowFacts;
|
|
21113
|
+
if (!facts || typeof facts !== "object" || Array.isArray(facts)) return void 0;
|
|
21114
|
+
const value = facts[step.targetFact];
|
|
21115
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
21116
|
+
}
|
|
21021
21117
|
function workflowIssueNumber(parent) {
|
|
21022
21118
|
return typeof parent.target === "number" ? parent.target : targetFromCliArgs(parent.cliArgs);
|
|
21023
21119
|
}
|
|
@@ -23032,8 +23128,10 @@ ${CI_HELP}`);
|
|
|
23032
23128
|
`);
|
|
23033
23129
|
const buildOnly = dispatch2.implementation === "preview-build";
|
|
23034
23130
|
if (args.skipInstall || buildOnly) {
|
|
23035
|
-
process.stdout.write(
|
|
23036
|
-
|
|
23131
|
+
process.stdout.write(
|
|
23132
|
+
`\u2192 kody: skipping dep install (${buildOnly ? "build-only implementation" : "--skip-install"})
|
|
23133
|
+
`
|
|
23134
|
+
);
|
|
23037
23135
|
} else {
|
|
23038
23136
|
const code = installDeps(pm, cwd);
|
|
23039
23137
|
if (code !== 0) {
|
|
@@ -26206,7 +26304,8 @@ Usage:
|
|
|
26206
26304
|
kody-engine release --issue <N> [--cwd <path>] [--verbose|--quiet]
|
|
26207
26305
|
kody-engine init [--cwd <path>] [--verbose|--quiet]
|
|
26208
26306
|
kody-engine <action> [--cwd <path>] [--verbose|--quiet]
|
|
26209
|
-
kody-engine
|
|
26307
|
+
kody-engine exec <name> [--cwd <path>] [--verbose|--quiet]
|
|
26308
|
+
kody-engine implementation <name> [--cwd <path>] [--verbose|--quiet]
|
|
26210
26309
|
kody-engine ci [preflight flags \u2014 see: kody-engine ci --help]
|
|
26211
26310
|
kody-engine chat [chat flags \u2014 see: kody-engine chat --help]
|
|
26212
26311
|
kody-engine stats [--since 7d|--run <id>|--json|--cwd <path>]
|
|
@@ -26214,7 +26313,7 @@ Usage:
|
|
|
26214
26313
|
kody-engine version
|
|
26215
26314
|
|
|
26216
26315
|
Top-level work commands are capabilities. A capability owns the public command name
|
|
26217
|
-
and resolves the implementation that runs it. Use the
|
|
26316
|
+
and resolves the implementation that runs it. Use the exec command only for
|
|
26218
26317
|
internal implementation profiles and scheduled helpers.
|
|
26219
26318
|
|
|
26220
26319
|
Exit codes:
|
|
@@ -26250,10 +26349,10 @@ function parseArgs(argv) {
|
|
|
26250
26349
|
if (cmd === "stats") {
|
|
26251
26350
|
return { ...result, command: "stats", statsArgv: argv.slice(1) };
|
|
26252
26351
|
}
|
|
26253
|
-
if (cmd === "implementation") {
|
|
26352
|
+
if (cmd === "implementation" || cmd === "exec") {
|
|
26254
26353
|
const implementationName = argv[1];
|
|
26255
26354
|
if (!implementationName || implementationName.startsWith("-")) {
|
|
26256
|
-
result.errors.push(
|
|
26355
|
+
result.errors.push(`${cmd} requires a name`);
|
|
26257
26356
|
return result;
|
|
26258
26357
|
}
|
|
26259
26358
|
if (!resolveImplementation(implementationName)) {
|
|
@@ -26288,7 +26387,7 @@ function parseArgs(argv) {
|
|
|
26288
26387
|
return result;
|
|
26289
26388
|
}
|
|
26290
26389
|
const discoveredActions = listCapabilityActions().map((e) => e.action);
|
|
26291
|
-
const available = ["ci", "chat", "stats", "implementation", "help", "version", ...discoveredActions];
|
|
26390
|
+
const available = ["ci", "chat", "stats", "exec", "implementation", "help", "version", ...discoveredActions];
|
|
26292
26391
|
result.errors.push(`unknown command: ${cmd} (available: ${available.join(", ")})`);
|
|
26293
26392
|
return result;
|
|
26294
26393
|
}
|