@kody-ade/kody-engine 0.4.264 → 0.4.265
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/kody.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "@kody-ade/kody-engine",
|
|
18
|
-
version: "0.4.
|
|
18
|
+
version: "0.4.265",
|
|
19
19
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
20
20
|
license: "MIT",
|
|
21
21
|
type: "module",
|
|
@@ -763,6 +763,8 @@ function parseReleaseConfig(raw) {
|
|
|
763
763
|
if (typeof r.publishCommand === "string") out.publishCommand = r.publishCommand;
|
|
764
764
|
if (typeof r.notifyCommand === "string") out.notifyCommand = r.notifyCommand;
|
|
765
765
|
if (typeof r.e2eCommand === "string") out.e2eCommand = r.e2eCommand;
|
|
766
|
+
if (typeof r.productionUrl === "string") out.productionUrl = r.productionUrl;
|
|
767
|
+
if (typeof r.smokeCommand === "string") out.smokeCommand = r.smokeCommand;
|
|
766
768
|
if (typeof r.draftRelease === "boolean") out.draftRelease = r.draftRelease;
|
|
767
769
|
if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
|
|
768
770
|
if (typeof r.timeoutMs === "number" && r.timeoutMs > 0) out.timeoutMs = Math.floor(r.timeoutMs);
|
|
@@ -1407,12 +1409,12 @@ function parseCapabilityConfig(raw) {
|
|
|
1407
1409
|
capabilityTools: tools,
|
|
1408
1410
|
implementations,
|
|
1409
1411
|
executables: stringList(raw.executables),
|
|
1410
|
-
capabilityKind: capabilityKindField(raw.capabilityKind),
|
|
1411
1412
|
role: stringField(raw.role),
|
|
1412
1413
|
describe: stringField(raw.describe),
|
|
1413
1414
|
stage: stringField(raw.stage),
|
|
1414
1415
|
readsFrom: stringList(raw.readsFrom ?? raw.reads_from),
|
|
1415
|
-
writesTo: stringList(raw.writesTo ?? raw.writes_to)
|
|
1416
|
+
writesTo: stringList(raw.writesTo ?? raw.writes_to),
|
|
1417
|
+
workflow: parseWorkflow(raw.workflow)
|
|
1416
1418
|
};
|
|
1417
1419
|
}
|
|
1418
1420
|
function parseCapabilityBody(raw, slug2) {
|
|
@@ -1448,9 +1450,44 @@ function stringList(value) {
|
|
|
1448
1450
|
}
|
|
1449
1451
|
return [];
|
|
1450
1452
|
}
|
|
1451
|
-
function
|
|
1452
|
-
|
|
1453
|
-
|
|
1453
|
+
function parseWorkflow(value) {
|
|
1454
|
+
const stepsRaw = Array.isArray(value) ? value : value && typeof value === "object" && Array.isArray(value.steps) ? value.steps : [];
|
|
1455
|
+
const steps = stepsRaw.map(parseWorkflowStep).filter((step) => step !== null);
|
|
1456
|
+
return steps.length > 0 ? { steps } : void 0;
|
|
1457
|
+
}
|
|
1458
|
+
function parseWorkflowStep(value) {
|
|
1459
|
+
if (typeof value === "string") {
|
|
1460
|
+
const capability2 = value.trim();
|
|
1461
|
+
return isSafeSlug(capability2) ? { capability: capability2 } : null;
|
|
1462
|
+
}
|
|
1463
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
1464
|
+
const raw = value;
|
|
1465
|
+
const capability = stringField(raw.capability ?? raw.action);
|
|
1466
|
+
if (!capability || !isSafeSlug(capability)) return null;
|
|
1467
|
+
const executable = stringField(raw.executable ?? raw.implementation);
|
|
1468
|
+
const action = stringField(raw.action);
|
|
1469
|
+
const agent = stringField(raw.agent);
|
|
1470
|
+
const reason = stringField(raw.reason);
|
|
1471
|
+
const target = stringField(raw.target);
|
|
1472
|
+
const cliArgs = raw.cliArgs;
|
|
1473
|
+
return {
|
|
1474
|
+
capability,
|
|
1475
|
+
...action && isSafeSlug(action) ? { action } : {},
|
|
1476
|
+
...executable && isSafeSlug(executable) ? { executable } : {},
|
|
1477
|
+
...target === "issue" || target === "pr" ? { target } : {},
|
|
1478
|
+
...agent && isSafeSlug(agent) ? { agent } : {},
|
|
1479
|
+
...reason ? { reason } : {},
|
|
1480
|
+
...cliArgs && typeof cliArgs === "object" && !Array.isArray(cliArgs) ? { cliArgs } : {},
|
|
1481
|
+
...isPlainObject(raw.runWhen) ? { runWhen: raw.runWhen } : {},
|
|
1482
|
+
...stringList(raw.continueOn ?? raw.continue_on).length > 0 ? { continueOn: stringList(raw.continueOn ?? raw.continue_on) } : {},
|
|
1483
|
+
...raw.saveReport === true ? { saveReport: true } : {}
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
function isPlainObject(value) {
|
|
1487
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1488
|
+
}
|
|
1489
|
+
function isSafeSlug(value) {
|
|
1490
|
+
return /^[a-z][a-z0-9-]*$/.test(value) && !value.includes("..");
|
|
1454
1491
|
}
|
|
1455
1492
|
var CAPABILITY_PROFILE_FILE, CAPABILITY_BODY_FILE;
|
|
1456
1493
|
var init_capabilityFolders = __esm({
|
|
@@ -1483,7 +1520,8 @@ function getCompanyStoreAssetRoot(kind) {
|
|
|
1483
1520
|
capabilities: "capabilities",
|
|
1484
1521
|
executables: "executables",
|
|
1485
1522
|
goals: "goals",
|
|
1486
|
-
agents: "agents"
|
|
1523
|
+
agents: "agents",
|
|
1524
|
+
workflows: "workflows"
|
|
1487
1525
|
};
|
|
1488
1526
|
return path7.join(root, ".kody", folderByKind[kind]);
|
|
1489
1527
|
}
|
|
@@ -1678,13 +1716,13 @@ function listCapabilityActions(projectCapabilitiesRoot = getProjectCapabilitiesR
|
|
|
1678
1716
|
const projectExecutableRoots = [getProjectExecutablesRoot()];
|
|
1679
1717
|
const storeExecutableRoot = getCompanyStoreExecutablesRoot();
|
|
1680
1718
|
const storeExecutableRoots = storeExecutableRoot ? [storeExecutableRoot] : [];
|
|
1681
|
-
for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder"
|
|
1719
|
+
for (const action of listFolderCapabilityActions(projectCapabilitiesRoot, "project-folder"))
|
|
1682
1720
|
add(action);
|
|
1683
1721
|
for (const root of projectExecutableRoots) {
|
|
1684
1722
|
for (const action of listExecutableCapabilityActions(root, "project-executable")) add(action);
|
|
1685
1723
|
}
|
|
1686
1724
|
if (storeCapabilitiesRoot) {
|
|
1687
|
-
for (const action of listFolderCapabilityActions(storeCapabilitiesRoot, "company-store"
|
|
1725
|
+
for (const action of listFolderCapabilityActions(storeCapabilitiesRoot, "company-store")) add(action);
|
|
1688
1726
|
}
|
|
1689
1727
|
for (const root of storeExecutableRoots) {
|
|
1690
1728
|
for (const action of listExecutableCapabilityActions(root, "company-store-executable")) add(action);
|
|
@@ -1707,7 +1745,16 @@ function resolveCapabilityFolder(slug2, projectCapabilitiesRoot = getProjectCapa
|
|
|
1707
1745
|
}
|
|
1708
1746
|
return null;
|
|
1709
1747
|
}
|
|
1748
|
+
function getCapabilityActionInputs(action) {
|
|
1749
|
+
const resolved = resolveCapabilityAction(action);
|
|
1750
|
+
if (!resolved) return null;
|
|
1751
|
+
return getProfileInputs(resolved.executable);
|
|
1752
|
+
}
|
|
1710
1753
|
function resolveCapabilityExecution(capability) {
|
|
1754
|
+
const firstWorkflowStep = capability.config.workflow?.steps[0];
|
|
1755
|
+
if (firstWorkflowStep) {
|
|
1756
|
+
return { executable: firstWorkflowStep.executable ?? firstWorkflowStep.capability, cliArgs: {} };
|
|
1757
|
+
}
|
|
1711
1758
|
const executable = capability.config.implementation ?? capability.config.executable ?? capability.config.implementations?.[0] ?? capability.config.executables?.[0] ?? (capability.config.role ? capability.slug : void 0) ?? (capability.config.tickScript ? "capability-tick-scripted" : "capability-tick");
|
|
1712
1759
|
const cliArgs = executableDeclaresInput(executable, "capability") ? { capability: capability.slug } : {};
|
|
1713
1760
|
return { executable, cliArgs };
|
|
@@ -1755,7 +1802,7 @@ function listExecutableCapabilityActions(root, source) {
|
|
|
1755
1802
|
const action = typeof raw.action === "string" && raw.action.trim() ? raw.action.trim() : "";
|
|
1756
1803
|
if (!action) continue;
|
|
1757
1804
|
if (!PUBLIC_EXECUTABLE_ROLES.has(String(raw.role))) continue;
|
|
1758
|
-
if (!
|
|
1805
|
+
if (typeof raw.kind !== "string" || !raw.kind.trim()) continue;
|
|
1759
1806
|
if (!Array.isArray(raw.inputs)) continue;
|
|
1760
1807
|
out.push({
|
|
1761
1808
|
action,
|
|
@@ -1771,14 +1818,13 @@ function listExecutableCapabilityActions(root, source) {
|
|
|
1771
1818
|
}
|
|
1772
1819
|
return out.sort((a, b) => a.action.localeCompare(b.action));
|
|
1773
1820
|
}
|
|
1774
|
-
function listFolderCapabilityActions(root, source
|
|
1821
|
+
function listFolderCapabilityActions(root, source) {
|
|
1775
1822
|
if (!fs6.existsSync(root) || !fs6.statSync(root).isDirectory()) return [];
|
|
1776
1823
|
const out = [];
|
|
1777
1824
|
for (const slug2 of listCapabilityFolderSlugs(root)) {
|
|
1778
1825
|
if (!isSafeName(slug2)) continue;
|
|
1779
1826
|
const capability = readCapabilityFolder(root, slug2);
|
|
1780
1827
|
if (!capability) continue;
|
|
1781
|
-
if (requireCapabilityKind && !capability.config.capabilityKind) continue;
|
|
1782
1828
|
const action = capability.config.action ?? slug2;
|
|
1783
1829
|
const { executable, cliArgs } = resolveCapabilityExecution(capability);
|
|
1784
1830
|
out.push({
|
|
@@ -1788,7 +1834,6 @@ function listFolderCapabilityActions(root, source, requireCapabilityKind = false
|
|
|
1788
1834
|
cliArgs,
|
|
1789
1835
|
source,
|
|
1790
1836
|
describe: capability.config.describe ?? capability.title,
|
|
1791
|
-
capabilityKind: capability.config.capabilityKind,
|
|
1792
1837
|
profilePath: capability.profilePath,
|
|
1793
1838
|
bodyPath: capability.bodyPath
|
|
1794
1839
|
});
|
|
@@ -1811,7 +1856,6 @@ function listBuiltinCapabilityActions(root = getBuiltinCapabilitiesRoot()) {
|
|
|
1811
1856
|
cliArgs: {},
|
|
1812
1857
|
source: "builtin",
|
|
1813
1858
|
describe: capability.config.describe ?? capability.title,
|
|
1814
|
-
capabilityKind: capability.config.capabilityKind,
|
|
1815
1859
|
profilePath: capability.profilePath,
|
|
1816
1860
|
bodyPath: capability.bodyPath
|
|
1817
1861
|
});
|
|
@@ -1854,14 +1898,13 @@ function parseGenericFlags(argv) {
|
|
|
1854
1898
|
if (positional.length > 0) args._ = positional;
|
|
1855
1899
|
return args;
|
|
1856
1900
|
}
|
|
1857
|
-
var PUBLIC_EXECUTABLE_ROLES
|
|
1901
|
+
var PUBLIC_EXECUTABLE_ROLES;
|
|
1858
1902
|
var init_registry = __esm({
|
|
1859
1903
|
"src/registry.ts"() {
|
|
1860
1904
|
"use strict";
|
|
1861
1905
|
init_capabilityFolders();
|
|
1862
1906
|
init_companyStore();
|
|
1863
1907
|
PUBLIC_EXECUTABLE_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
1864
|
-
PUBLIC_EXECUTABLE_CAPABILITY_KINDS = /* @__PURE__ */ new Set(["observe", "act", "verify"]);
|
|
1865
1908
|
}
|
|
1866
1909
|
});
|
|
1867
1910
|
|
|
@@ -3090,6 +3133,60 @@ var init_gha = __esm({
|
|
|
3090
3133
|
}
|
|
3091
3134
|
});
|
|
3092
3135
|
|
|
3136
|
+
// src/agents.ts
|
|
3137
|
+
import * as fs16 from "fs";
|
|
3138
|
+
import * as path16 from "path";
|
|
3139
|
+
function stripFrontmatter(raw) {
|
|
3140
|
+
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
3141
|
+
return (match ? match[1] : raw).trim();
|
|
3142
|
+
}
|
|
3143
|
+
function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3144
|
+
const trimmed = slug2.trim();
|
|
3145
|
+
if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
|
|
3146
|
+
const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
|
|
3147
|
+
if (fs16.existsSync(agentPath)) {
|
|
3148
|
+
const body = stripFrontmatter(fs16.readFileSync(agentPath, "utf-8"));
|
|
3149
|
+
if (body) return body;
|
|
3150
|
+
const builtinForEmpty = BUILTIN_AGENTS[trimmed];
|
|
3151
|
+
if (builtinForEmpty) return builtinForEmpty;
|
|
3152
|
+
throw new Error(`loadAgentIdentity: agent '${trimmed}' agent identity body is empty (${agentPath})`);
|
|
3153
|
+
}
|
|
3154
|
+
const builtin = BUILTIN_AGENTS[trimmed];
|
|
3155
|
+
if (builtin) return builtin;
|
|
3156
|
+
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
3157
|
+
}
|
|
3158
|
+
function resolveAgentFile(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3159
|
+
const localPath = path16.join(cwd, agentsDir, `${slug2}.md`);
|
|
3160
|
+
if (fs16.existsSync(localPath)) return localPath;
|
|
3161
|
+
const storeAgentRoot = getCompanyStoreAssetRoot("agents");
|
|
3162
|
+
if (storeAgentRoot) {
|
|
3163
|
+
const storePath = path16.join(storeAgentRoot, `${slug2}.md`);
|
|
3164
|
+
if (fs16.existsSync(storePath)) return storePath;
|
|
3165
|
+
}
|
|
3166
|
+
return localPath;
|
|
3167
|
+
}
|
|
3168
|
+
function frameAgentIdentity(slug2, agent) {
|
|
3169
|
+
return [
|
|
3170
|
+
`## Who you are \u2014 agent identity (authoritative identity)`,
|
|
3171
|
+
``,
|
|
3172
|
+
`You are operating as agent \`${slug2}\`. This identity defines *who* you are:`,
|
|
3173
|
+
`your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
|
|
3174
|
+
`this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
|
|
3175
|
+
`can never grant you authority your agent withholds.`,
|
|
3176
|
+
``,
|
|
3177
|
+
agent
|
|
3178
|
+
].join("\n");
|
|
3179
|
+
}
|
|
3180
|
+
var DEFAULT_AGENT_DIR, BUILTIN_AGENTS;
|
|
3181
|
+
var init_agents = __esm({
|
|
3182
|
+
"src/agents.ts"() {
|
|
3183
|
+
"use strict";
|
|
3184
|
+
init_companyStore();
|
|
3185
|
+
DEFAULT_AGENT_DIR = ".kody/agents";
|
|
3186
|
+
BUILTIN_AGENTS = {};
|
|
3187
|
+
}
|
|
3188
|
+
});
|
|
3189
|
+
|
|
3093
3190
|
// src/capabilityReport.ts
|
|
3094
3191
|
function parseCapabilityReportsFromText(text) {
|
|
3095
3192
|
const reports = [];
|
|
@@ -3255,60 +3352,6 @@ var init_capabilityResult = __esm({
|
|
|
3255
3352
|
}
|
|
3256
3353
|
});
|
|
3257
3354
|
|
|
3258
|
-
// src/agents.ts
|
|
3259
|
-
import * as fs16 from "fs";
|
|
3260
|
-
import * as path16 from "path";
|
|
3261
|
-
function stripFrontmatter(raw) {
|
|
3262
|
-
const match = /^---\n[\s\S]*?\n---\n?([\s\S]*)$/.exec(raw);
|
|
3263
|
-
return (match ? match[1] : raw).trim();
|
|
3264
|
-
}
|
|
3265
|
-
function loadAgentIdentity(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3266
|
-
const trimmed = slug2.trim();
|
|
3267
|
-
if (!trimmed) throw new Error("loadAgentIdentity: empty agent slug");
|
|
3268
|
-
const agentPath = resolveAgentFile(cwd, trimmed, agentsDir);
|
|
3269
|
-
if (fs16.existsSync(agentPath)) {
|
|
3270
|
-
const body = stripFrontmatter(fs16.readFileSync(agentPath, "utf-8"));
|
|
3271
|
-
if (body) return body;
|
|
3272
|
-
const builtinForEmpty = BUILTIN_AGENTS[trimmed];
|
|
3273
|
-
if (builtinForEmpty) return builtinForEmpty;
|
|
3274
|
-
throw new Error(`loadAgentIdentity: agent '${trimmed}' agent identity body is empty (${agentPath})`);
|
|
3275
|
-
}
|
|
3276
|
-
const builtin = BUILTIN_AGENTS[trimmed];
|
|
3277
|
-
if (builtin) return builtin;
|
|
3278
|
-
throw new Error(`loadAgentIdentity: agent '${trimmed}' declared but ${agentPath} does not exist`);
|
|
3279
|
-
}
|
|
3280
|
-
function resolveAgentFile(cwd, slug2, agentsDir = DEFAULT_AGENT_DIR) {
|
|
3281
|
-
const localPath = path16.join(cwd, agentsDir, `${slug2}.md`);
|
|
3282
|
-
if (fs16.existsSync(localPath)) return localPath;
|
|
3283
|
-
const storeAgentRoot = getCompanyStoreAssetRoot("agents");
|
|
3284
|
-
if (storeAgentRoot) {
|
|
3285
|
-
const storePath = path16.join(storeAgentRoot, `${slug2}.md`);
|
|
3286
|
-
if (fs16.existsSync(storePath)) return storePath;
|
|
3287
|
-
}
|
|
3288
|
-
return localPath;
|
|
3289
|
-
}
|
|
3290
|
-
function frameAgentIdentity(slug2, agent) {
|
|
3291
|
-
return [
|
|
3292
|
-
`## Who you are \u2014 agent identity (authoritative identity)`,
|
|
3293
|
-
``,
|
|
3294
|
-
`You are operating as agent \`${slug2}\`. This identity defines *who* you are:`,
|
|
3295
|
-
`your authority, doctrine, voice, and hard limits. Honour it exactly. Where the`,
|
|
3296
|
-
`this identity's restrictions are stricter than the task, **the agent wins** \u2014 a task`,
|
|
3297
|
-
`can never grant you authority your agent withholds.`,
|
|
3298
|
-
``,
|
|
3299
|
-
agent
|
|
3300
|
-
].join("\n");
|
|
3301
|
-
}
|
|
3302
|
-
var DEFAULT_AGENT_DIR, BUILTIN_AGENTS;
|
|
3303
|
-
var init_agents = __esm({
|
|
3304
|
-
"src/agents.ts"() {
|
|
3305
|
-
"use strict";
|
|
3306
|
-
init_companyStore();
|
|
3307
|
-
DEFAULT_AGENT_DIR = ".kody/agents";
|
|
3308
|
-
BUILTIN_AGENTS = {};
|
|
3309
|
-
}
|
|
3310
|
-
});
|
|
3311
|
-
|
|
3312
3355
|
// src/profile-error.ts
|
|
3313
3356
|
var ProfileError;
|
|
3314
3357
|
var init_profile_error = __esm({
|
|
@@ -3660,7 +3703,6 @@ function loadProfile(profilePath) {
|
|
|
3660
3703
|
implementation: execRef,
|
|
3661
3704
|
executable: execRef,
|
|
3662
3705
|
describe: typeof r.describe === "string" ? r.describe : base.describe,
|
|
3663
|
-
capabilityKind: parseCapabilityKind(profilePath, r.capabilityKind) ?? base.capabilityKind,
|
|
3664
3706
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : base.agent,
|
|
3665
3707
|
capabilityTools: parseStringArray2(r.capabilityTools ?? r.capabilityTools ?? r.tools) ?? base.capabilityTools,
|
|
3666
3708
|
mentions: Array.isArray(r.mentions) ? r.mentions.map((m) => String(m).trim()).filter(Boolean) : base.mentions
|
|
@@ -3705,7 +3747,6 @@ function loadProfile(profilePath) {
|
|
|
3705
3747
|
implementation: void 0,
|
|
3706
3748
|
executable: void 0,
|
|
3707
3749
|
describe: typeof r.describe === "string" ? r.describe : "",
|
|
3708
|
-
capabilityKind: parseCapabilityKind(profilePath, r.capabilityKind),
|
|
3709
3750
|
// Optional agent to run as. Empty/blank string → undefined (no agent).
|
|
3710
3751
|
agent: typeof r.agent === "string" && r.agent.trim() ? r.agent.trim() : void 0,
|
|
3711
3752
|
// Locked-toolbox palette + mentions from folder-capability profile metadata.
|
|
@@ -3800,13 +3841,6 @@ function requireString(p, r, key) {
|
|
|
3800
3841
|
}
|
|
3801
3842
|
return v;
|
|
3802
3843
|
}
|
|
3803
|
-
function parseCapabilityKind(p, raw) {
|
|
3804
|
-
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
3805
|
-
if (typeof raw !== "string" || !VALID_CAPABILITY_KINDS.has(raw)) {
|
|
3806
|
-
throw new ProfileError(p, `"capabilityKind" must be one of: observe | act | verify`);
|
|
3807
|
-
}
|
|
3808
|
-
return raw;
|
|
3809
|
-
}
|
|
3810
3844
|
function parseStringArray2(raw) {
|
|
3811
3845
|
if (!Array.isArray(raw)) return void 0;
|
|
3812
3846
|
const values = raw.map((t) => String(t).trim()).filter(Boolean);
|
|
@@ -4053,7 +4087,7 @@ function parseScriptList(p, key, raw) {
|
|
|
4053
4087
|
}
|
|
4054
4088
|
return out;
|
|
4055
4089
|
}
|
|
4056
|
-
var VALID_INPUT_TYPES, VALID_PERMISSION_MODES, VALID_ROLES, VALID_CONTAINER_CHILD_TARGETS, VALID_PHASES,
|
|
4090
|
+
var VALID_INPUT_TYPES, VALID_PERMISSION_MODES, VALID_ROLES, VALID_CONTAINER_CHILD_TARGETS, VALID_PHASES, KNOWN_PROFILE_KEYS;
|
|
4057
4091
|
var init_profile = __esm({
|
|
4058
4092
|
"src/profile.ts"() {
|
|
4059
4093
|
"use strict";
|
|
@@ -4069,7 +4103,6 @@ var init_profile = __esm({
|
|
|
4069
4103
|
VALID_ROLES = /* @__PURE__ */ new Set(["primitive", "orchestrator", "container", "watch", "utility"]);
|
|
4070
4104
|
VALID_CONTAINER_CHILD_TARGETS = /* @__PURE__ */ new Set(["issue", "pr"]);
|
|
4071
4105
|
VALID_PHASES = /* @__PURE__ */ new Set(["research", "planning", "implementing", "reviewing", "shipped", "failed", "idle"]);
|
|
4072
|
-
VALID_CAPABILITY_KINDS = /* @__PURE__ */ new Set(["observe", "act", "verify"]);
|
|
4073
4106
|
KNOWN_PROFILE_KEYS = /* @__PURE__ */ new Set([
|
|
4074
4107
|
"name",
|
|
4075
4108
|
"action",
|
|
@@ -4083,10 +4116,10 @@ var init_profile = __esm({
|
|
|
4083
4116
|
"capabilityTools",
|
|
4084
4117
|
"tools",
|
|
4085
4118
|
"mentions",
|
|
4086
|
-
"capabilityKind",
|
|
4087
4119
|
"stage",
|
|
4088
4120
|
"readsFrom",
|
|
4089
4121
|
"writesTo",
|
|
4122
|
+
"workflow",
|
|
4090
4123
|
"describe",
|
|
4091
4124
|
"role",
|
|
4092
4125
|
"kind",
|
|
@@ -6078,7 +6111,7 @@ function asPreferredRunTime(value) {
|
|
|
6078
6111
|
function asLoopTarget(value) {
|
|
6079
6112
|
const raw = asRecord(value);
|
|
6080
6113
|
if (!raw) return void 0;
|
|
6081
|
-
if (raw.type !== "goal" && raw.type !== "capability") return void 0;
|
|
6114
|
+
if (raw.type !== "goal" && raw.type !== "capability" && raw.type !== "workflow") return void 0;
|
|
6082
6115
|
if (typeof raw.id !== "string" || raw.id.trim().length === 0) return void 0;
|
|
6083
6116
|
return { type: raw.type, id: raw.id };
|
|
6084
6117
|
}
|
|
@@ -6174,10 +6207,10 @@ var init_state2 = __esm({
|
|
|
6174
6207
|
"use strict";
|
|
6175
6208
|
VALID_STATES = /* @__PURE__ */ new Set(["active", "abandoned", "closed", "done"]);
|
|
6176
6209
|
GoalStateError = class extends Error {
|
|
6177
|
-
constructor(
|
|
6178
|
-
super(`Invalid goal state at ${
|
|
6210
|
+
constructor(path49, message) {
|
|
6211
|
+
super(`Invalid goal state at ${path49}:
|
|
6179
6212
|
${message}`);
|
|
6180
|
-
this.path =
|
|
6213
|
+
this.path = path49;
|
|
6181
6214
|
this.name = "GoalStateError";
|
|
6182
6215
|
}
|
|
6183
6216
|
path;
|
|
@@ -6190,17 +6223,12 @@ import * as fs25 from "fs";
|
|
|
6190
6223
|
function stageGoalRunLogEvent(data, goalId, event, at = nowIso()) {
|
|
6191
6224
|
const logs = goalRunLogs(data);
|
|
6192
6225
|
const existing = logs[goalId];
|
|
6193
|
-
const
|
|
6226
|
+
const path49 = existing?.path ?? goalRunLogPath(goalId, data);
|
|
6194
6227
|
logs[goalId] = {
|
|
6195
|
-
path:
|
|
6228
|
+
path: path49,
|
|
6196
6229
|
events: [
|
|
6197
6230
|
...existing?.events ?? [],
|
|
6198
|
-
|
|
6199
|
-
version: 1,
|
|
6200
|
-
time: at,
|
|
6201
|
-
goalId,
|
|
6202
|
-
...event
|
|
6203
|
-
}
|
|
6231
|
+
buildGoalRunLogEvent(data, goalId, event, at)
|
|
6204
6232
|
]
|
|
6205
6233
|
};
|
|
6206
6234
|
}
|
|
@@ -6298,15 +6326,33 @@ function githubRunId() {
|
|
|
6298
6326
|
const attempt = process.env.GITHUB_RUN_ATTEMPT?.trim();
|
|
6299
6327
|
return attempt ? `gh-${runId}-${attempt}` : `gh-${runId}`;
|
|
6300
6328
|
}
|
|
6329
|
+
function buildGoalRunLogEvent(data, goalId, event, at) {
|
|
6330
|
+
const trigger = event.trigger ?? triggerContext();
|
|
6331
|
+
const job = event.job ?? jobContext(data);
|
|
6332
|
+
const base = {
|
|
6333
|
+
version: 1,
|
|
6334
|
+
time: at,
|
|
6335
|
+
goalId,
|
|
6336
|
+
...event
|
|
6337
|
+
};
|
|
6338
|
+
if (trigger !== void 0) base.trigger = trigger;
|
|
6339
|
+
if (job !== void 0) base.job = job;
|
|
6340
|
+
const context = event.dispatchContext ?? dispatchContext(base, trigger, job);
|
|
6341
|
+
if (context !== void 0) base.dispatchContext = context;
|
|
6342
|
+
return base;
|
|
6343
|
+
}
|
|
6301
6344
|
function enrichGoalRunLogEvent(config, data, logPath, event) {
|
|
6302
6345
|
const stateRepo = stateRepoContext(config, event.goalId, logPath);
|
|
6346
|
+
const trigger = event.trigger ?? triggerContext();
|
|
6347
|
+
const job = event.job ?? jobContext(data);
|
|
6303
6348
|
return pruneUndefined({
|
|
6304
6349
|
...event,
|
|
6305
6350
|
run: event.run ?? runContext(data),
|
|
6306
6351
|
repo: event.repo ?? repoContext(config),
|
|
6307
6352
|
stateRepo: event.stateRepo ?? stateRepo,
|
|
6308
|
-
trigger
|
|
6309
|
-
job
|
|
6353
|
+
trigger,
|
|
6354
|
+
job,
|
|
6355
|
+
dispatchContext: event.dispatchContext ?? dispatchContext(event, trigger, job),
|
|
6310
6356
|
links: event.links ?? linkContext(stateRepo)
|
|
6311
6357
|
});
|
|
6312
6358
|
}
|
|
@@ -6353,9 +6399,16 @@ function stateRepoContext(config, goalId, logPath) {
|
|
|
6353
6399
|
function triggerContext() {
|
|
6354
6400
|
const event = readGithubEvent();
|
|
6355
6401
|
const inputs = recordValue2(event?.inputs);
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6402
|
+
const eventName = process.env.GITHUB_EVENT_NAME?.trim() || void 0;
|
|
6403
|
+
const githubActor = process.env.GITHUB_ACTOR?.trim() || void 0;
|
|
6404
|
+
if (!eventName && !githubActor && !process.env.GITHUB_EVENT_PATH) return void 0;
|
|
6405
|
+
const trigger = pruneUndefined({
|
|
6406
|
+
source: eventName ? "github-actions" : "local",
|
|
6407
|
+
kind: triggerKind(eventName),
|
|
6408
|
+
eventName,
|
|
6409
|
+
actor: githubActor,
|
|
6410
|
+
githubActor,
|
|
6411
|
+
actorRole: triggerActorRole(eventName),
|
|
6359
6412
|
eventPath: process.env.GITHUB_EVENT_PATH?.trim() || void 0,
|
|
6360
6413
|
issue: numberValue(recordValue2(event?.issue)?.number),
|
|
6361
6414
|
pullRequest: numberValue(recordValue2(event?.pull_request)?.number),
|
|
@@ -6363,23 +6416,70 @@ function triggerContext() {
|
|
|
6363
6416
|
schedule: stringValue(event?.schedule),
|
|
6364
6417
|
inputs: inputs ? pickRecord(inputs, ["issue_number", "sessionId", "message", "model", "title", "executable", "base"]) : void 0
|
|
6365
6418
|
});
|
|
6419
|
+
return Object.keys(trigger).length > 0 ? trigger : void 0;
|
|
6420
|
+
}
|
|
6421
|
+
function triggerKind(eventName) {
|
|
6422
|
+
if (!eventName) return "local";
|
|
6423
|
+
if (eventName === "schedule") return "schedule";
|
|
6424
|
+
if (eventName === "workflow_dispatch") return "manual-workflow-dispatch";
|
|
6425
|
+
return eventName;
|
|
6426
|
+
}
|
|
6427
|
+
function triggerActorRole(eventName) {
|
|
6428
|
+
if (!eventName) return void 0;
|
|
6429
|
+
if (eventName === "schedule") return "github workflow run actor; not the manual dispatcher";
|
|
6430
|
+
if (eventName === "workflow_dispatch") return "manual workflow dispatcher";
|
|
6431
|
+
return "github event actor";
|
|
6366
6432
|
}
|
|
6367
6433
|
function jobContext(data) {
|
|
6368
6434
|
const job = pruneUndefined({
|
|
6369
|
-
id: stringValue(data.jobId),
|
|
6370
|
-
key: stringValue(data.jobKey),
|
|
6371
|
-
flavor: stringValue(data.jobFlavor),
|
|
6372
|
-
action: stringValue(data.jobAction),
|
|
6373
|
-
capability: stringValue(data.jobCapability),
|
|
6374
|
-
executable: stringValue(data.jobExecutable),
|
|
6375
|
-
agent: stringValue(data.jobAgent),
|
|
6376
|
-
schedule: stringValue(data.jobSchedule),
|
|
6377
|
-
target: data.jobTarget,
|
|
6435
|
+
id: stringValue(data.jobId) ?? void 0,
|
|
6436
|
+
key: stringValue(data.jobKey) ?? void 0,
|
|
6437
|
+
flavor: stringValue(data.jobFlavor) ?? void 0,
|
|
6438
|
+
action: stringValue(data.jobAction) ?? void 0,
|
|
6439
|
+
capability: stringValue(data.jobCapability) ?? void 0,
|
|
6440
|
+
executable: stringValue(data.jobExecutable) ?? void 0,
|
|
6441
|
+
agent: stringValue(data.jobAgent) ?? void 0,
|
|
6442
|
+
schedule: stringValue(data.jobSchedule) ?? void 0,
|
|
6443
|
+
target: data.jobTarget ?? void 0,
|
|
6378
6444
|
why: truncateString(stringValue(data.jobWhy), 1e3),
|
|
6379
6445
|
saveReport: data.jobSaveReport === true ? true : void 0
|
|
6380
6446
|
});
|
|
6381
6447
|
return Object.keys(job).length > 0 ? job : void 0;
|
|
6382
6448
|
}
|
|
6449
|
+
function dispatchContext(event, trigger, job) {
|
|
6450
|
+
if (!event.dispatch && event.status !== "dispatch") return void 0;
|
|
6451
|
+
const dispatch2 = event.dispatch ?? {};
|
|
6452
|
+
const context = pruneUndefined({
|
|
6453
|
+
triggeredBy: triggerLabel(trigger),
|
|
6454
|
+
triggerKind: stringValue(trigger?.kind),
|
|
6455
|
+
dispatchMode: dispatchMode(trigger),
|
|
6456
|
+
githubActor: stringValue(trigger?.githubActor) ?? stringValue(trigger?.actor),
|
|
6457
|
+
githubActorRole: stringValue(trigger?.actorRole),
|
|
6458
|
+
decidedBy: event.source,
|
|
6459
|
+
dispatchedBy: event.source,
|
|
6460
|
+
target: event.target,
|
|
6461
|
+
action: dispatch2.action ?? stringValue(job?.action),
|
|
6462
|
+
capability: dispatch2.capability ?? stringValue(job?.capability),
|
|
6463
|
+
reason: event.reason
|
|
6464
|
+
});
|
|
6465
|
+
return Object.keys(context).length > 0 ? context : void 0;
|
|
6466
|
+
}
|
|
6467
|
+
function triggerLabel(trigger) {
|
|
6468
|
+
const kind = stringValue(trigger?.kind);
|
|
6469
|
+
if (kind === "schedule") return "GitHub schedule";
|
|
6470
|
+
if (kind === "manual-workflow-dispatch") return "manual workflow dispatch";
|
|
6471
|
+
if (kind === "issue_comment") return "GitHub issue comment";
|
|
6472
|
+
if (kind === "pull_request") return "GitHub pull request";
|
|
6473
|
+
if (kind) return `GitHub ${kind}`;
|
|
6474
|
+
return "local run";
|
|
6475
|
+
}
|
|
6476
|
+
function dispatchMode(trigger) {
|
|
6477
|
+
const kind = stringValue(trigger?.kind);
|
|
6478
|
+
if (kind === "schedule") return "automated";
|
|
6479
|
+
if (kind === "manual-workflow-dispatch") return "manual";
|
|
6480
|
+
if (kind) return "event-driven";
|
|
6481
|
+
return "local";
|
|
6482
|
+
}
|
|
6383
6483
|
function linkContext(stateRepo) {
|
|
6384
6484
|
const links = {};
|
|
6385
6485
|
const runId = process.env.GITHUB_RUN_ID?.trim();
|
|
@@ -7004,12 +7104,20 @@ function isCapabilityCadenceGoal(goal, extra) {
|
|
|
7004
7104
|
function isGoalTargetLoop(goal) {
|
|
7005
7105
|
return goal.type === "agentLoop" && goal.loopTarget?.type === "goal" && goal.loopTarget.id.trim().length > 0;
|
|
7006
7106
|
}
|
|
7007
|
-
function
|
|
7107
|
+
function isWorkflowTargetLoop(goal) {
|
|
7108
|
+
return goal.type === "agentLoop" && goal.loopTarget?.type === "workflow" && goal.loopTarget.id.trim().length > 0;
|
|
7109
|
+
}
|
|
7110
|
+
function planTargetLoopSchedule(opts) {
|
|
7008
7111
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
7009
7112
|
const at = now.toISOString();
|
|
7010
|
-
const
|
|
7113
|
+
const target = opts.goal.loopTarget;
|
|
7114
|
+
const targetId = target?.id.trim() ?? "";
|
|
7011
7115
|
if (!targetId) {
|
|
7012
|
-
const reason = "
|
|
7116
|
+
const reason = "loop missing target";
|
|
7117
|
+
return targetLoopDecision("blocked", reason, at);
|
|
7118
|
+
}
|
|
7119
|
+
if (target?.type !== "goal" && target?.type !== "workflow") {
|
|
7120
|
+
const reason = `unsupported loop target: ${String(target?.type ?? "missing")}`;
|
|
7013
7121
|
return targetLoopDecision("blocked", reason, at);
|
|
7014
7122
|
}
|
|
7015
7123
|
const preferred = opts.goal.preferredRunTime;
|
|
@@ -7017,18 +7125,22 @@ function planGoalTargetLoopSchedule(opts) {
|
|
|
7017
7125
|
const gate = preferredRunTimeGate(preferred, now, opts.previousScheduleState);
|
|
7018
7126
|
if (!gate.ok) return targetLoopDecision("idle", gate.reason, at);
|
|
7019
7127
|
}
|
|
7128
|
+
const dispatch2 = target.type === "goal" ? { action: "goal-manager", executable: "goal-manager", cliArgs: { goal: targetId } } : { workflow: targetId, cliArgs: {} };
|
|
7020
7129
|
return {
|
|
7021
7130
|
kind: "dispatch",
|
|
7022
|
-
reason: `dispatch
|
|
7023
|
-
dispatch:
|
|
7131
|
+
reason: `dispatch ${target.type} ${targetId}`,
|
|
7132
|
+
dispatch: dispatch2,
|
|
7024
7133
|
scheduleState: {
|
|
7025
7134
|
mode: "agentLoop",
|
|
7026
7135
|
lastGoalTickAt: at,
|
|
7027
7136
|
lastDecision: {
|
|
7028
7137
|
kind: "dispatch",
|
|
7029
|
-
targetType:
|
|
7138
|
+
targetType: target.type,
|
|
7030
7139
|
targetId,
|
|
7031
|
-
|
|
7140
|
+
...dispatch2.action ? { action: dispatch2.action } : {},
|
|
7141
|
+
...dispatch2.capability ? { capability: dispatch2.capability } : {},
|
|
7142
|
+
...dispatch2.workflow ? { workflow: dispatch2.workflow } : {},
|
|
7143
|
+
...dispatch2.executable ? { executable: dispatch2.executable } : {},
|
|
7032
7144
|
reason: preferred ? `preferred time ${preferred.time} ${preferred.timezone}` : "ready target loop tick",
|
|
7033
7145
|
at
|
|
7034
7146
|
},
|
|
@@ -7238,8 +7350,8 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision, detai
|
|
|
7238
7350
|
status: decision.kind,
|
|
7239
7351
|
dispatch: {
|
|
7240
7352
|
capability: decision.capability,
|
|
7241
|
-
|
|
7242
|
-
|
|
7353
|
+
cliArgs: decision.cliArgs,
|
|
7354
|
+
...decision.executable ? { executable: decision.executable } : {}
|
|
7243
7355
|
},
|
|
7244
7356
|
goal: details.goalSnapshot,
|
|
7245
7357
|
inspection: details.inspection,
|
|
@@ -7248,8 +7360,8 @@ function stageManagedGoalDecision(data, goalId, goal, goalState, decision, detai
|
|
|
7248
7360
|
evidence: decision.evidence,
|
|
7249
7361
|
stage: decision.stage,
|
|
7250
7362
|
capability: decision.capability,
|
|
7251
|
-
|
|
7252
|
-
|
|
7363
|
+
cliArgs: decision.cliArgs,
|
|
7364
|
+
...decision.executable ? { executable: decision.executable } : {}
|
|
7253
7365
|
},
|
|
7254
7366
|
change: details.change
|
|
7255
7367
|
});
|
|
@@ -7444,18 +7556,20 @@ var init_advanceManagedGoal = __esm({
|
|
|
7444
7556
|
ctx.output.reason = reason;
|
|
7445
7557
|
return;
|
|
7446
7558
|
}
|
|
7447
|
-
if (isGoalTargetLoop(managed)) {
|
|
7559
|
+
if (isGoalTargetLoop(managed) || isWorkflowTargetLoop(managed)) {
|
|
7448
7560
|
const beforeSnapshot = goalRunLogSnapshot(goal.id, goal.state, managed);
|
|
7449
7561
|
const previousScheduleState = goal.raw.extra.scheduleState && typeof goal.raw.extra.scheduleState === "object" ? goal.raw.extra.scheduleState : void 0;
|
|
7450
|
-
const decision2 =
|
|
7562
|
+
const decision2 = planTargetLoopSchedule({ goal: managed, previousScheduleState });
|
|
7451
7563
|
restoreGoalIdFact();
|
|
7452
7564
|
goal.raw = writeManagedGoalToState({ ...goal.raw, state: goal.state }, managed);
|
|
7453
7565
|
goal.raw.extra.scheduleState = decision2.scheduleState;
|
|
7454
7566
|
ctx.data.managedGoalDecision = decision2;
|
|
7455
7567
|
if (decision2.kind === "dispatch" && decision2.dispatch) {
|
|
7456
7568
|
ctx.output.nextDispatch = {
|
|
7457
|
-
action: decision2.dispatch.action,
|
|
7458
|
-
|
|
7569
|
+
...decision2.dispatch.action ? { action: decision2.dispatch.action } : {},
|
|
7570
|
+
...decision2.dispatch.capability ? { capability: decision2.dispatch.capability } : {},
|
|
7571
|
+
...decision2.dispatch.workflow ? { workflow: decision2.dispatch.workflow } : {},
|
|
7572
|
+
...decision2.dispatch.executable ? { executable: decision2.dispatch.executable } : {},
|
|
7459
7573
|
cliArgs: decision2.dispatch.cliArgs
|
|
7460
7574
|
};
|
|
7461
7575
|
}
|
|
@@ -7576,8 +7690,8 @@ var init_advanceManagedGoal = __esm({
|
|
|
7576
7690
|
}
|
|
7577
7691
|
ctx.output.nextDispatch = {
|
|
7578
7692
|
capability: decision.capability,
|
|
7579
|
-
executable: decision.executable,
|
|
7580
7693
|
cliArgs: decision.cliArgs,
|
|
7694
|
+
...decision.executable ? { executable: decision.executable } : {},
|
|
7581
7695
|
...decision.saveReport === true ? { saveReport: true } : {}
|
|
7582
7696
|
};
|
|
7583
7697
|
ctx.output.reason = `dispatch ${decision.capability} for ${decision.evidence}`;
|
|
@@ -7817,13 +7931,13 @@ function companyIntentPath(id) {
|
|
|
7817
7931
|
assertIntentId(id);
|
|
7818
7932
|
return `intents/${id}/intent.json`;
|
|
7819
7933
|
}
|
|
7820
|
-
function normalizeCompanyIntent(
|
|
7934
|
+
function normalizeCompanyIntent(path49, raw) {
|
|
7821
7935
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
7822
|
-
throw new Error(`${
|
|
7936
|
+
throw new Error(`${path49}: intent must be JSON object`);
|
|
7823
7937
|
}
|
|
7824
7938
|
const input = raw;
|
|
7825
7939
|
const id = stringField2(input.id);
|
|
7826
|
-
if (!id || !isCompanyIntentId(id)) throw new Error(`${
|
|
7940
|
+
if (!id || !isCompanyIntentId(id)) throw new Error(`${path49}: invalid intent id`);
|
|
7827
7941
|
const createdAt = stringField2(input.createdAt) || nowIso();
|
|
7828
7942
|
const updatedAt = stringField2(input.updatedAt) || createdAt;
|
|
7829
7943
|
return {
|
|
@@ -7862,8 +7976,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
7862
7976
|
const records = [];
|
|
7863
7977
|
for (const entry of entries) {
|
|
7864
7978
|
if (entry.type !== "dir" || !entry.name || !isCompanyIntentId(entry.name)) continue;
|
|
7865
|
-
const
|
|
7866
|
-
const file = readStateText(config, cwd,
|
|
7979
|
+
const path49 = companyIntentPath(entry.name);
|
|
7980
|
+
const file = readStateText(config, cwd, path49);
|
|
7867
7981
|
if (!file) continue;
|
|
7868
7982
|
records.push({
|
|
7869
7983
|
id: entry.name,
|
|
@@ -7874,8 +7988,8 @@ function listCompanyIntents(config, cwd) {
|
|
|
7874
7988
|
return records.sort((a, b) => a.intent.priority - b.intent.priority || a.id.localeCompare(b.id));
|
|
7875
7989
|
}
|
|
7876
7990
|
function readCompanyIntent(config, cwd, id) {
|
|
7877
|
-
const
|
|
7878
|
-
const file = readStateText(config, cwd,
|
|
7991
|
+
const path49 = companyIntentPath(id);
|
|
7992
|
+
const file = readStateText(config, cwd, path49);
|
|
7879
7993
|
if (!file) return null;
|
|
7880
7994
|
return { id, path: file.path, intent: normalizeCompanyIntent(file.path, JSON.parse(file.content)) };
|
|
7881
7995
|
}
|
|
@@ -8362,6 +8476,9 @@ function goalReportBody(goalId, state, snapshot, latestEvent, evidenceItems) {
|
|
|
8362
8476
|
`- Missing evidence: ${listOrNone(missingEvidence)}`,
|
|
8363
8477
|
`- Blockers: ${listOrNone(blockers)}`,
|
|
8364
8478
|
"",
|
|
8479
|
+
"## Dispatch",
|
|
8480
|
+
...dispatchContextMarkdown(latestEvent),
|
|
8481
|
+
"",
|
|
8365
8482
|
"## Capability Evidence",
|
|
8366
8483
|
...capabilityEvidenceMarkdown(outputs),
|
|
8367
8484
|
"",
|
|
@@ -8399,6 +8516,27 @@ function evidenceOutputMarkdown(index, output) {
|
|
|
8399
8516
|
""
|
|
8400
8517
|
];
|
|
8401
8518
|
}
|
|
8519
|
+
function dispatchContextMarkdown(latestEvent) {
|
|
8520
|
+
const context = recordField2(latestEvent, "dispatchContext");
|
|
8521
|
+
if (!context) return ["- none"];
|
|
8522
|
+
const githubActor = stringField3(context, "githubActor");
|
|
8523
|
+
const githubActorRole = stringField3(context, "githubActorRole");
|
|
8524
|
+
const target = dispatchTargetLabel(recordField2(context, "target"));
|
|
8525
|
+
return [
|
|
8526
|
+
`- Triggered by: ${stringField3(context, "triggeredBy") ?? "unknown"}`,
|
|
8527
|
+
`- Mode: ${stringField3(context, "dispatchMode") ?? "unknown"}`,
|
|
8528
|
+
`- GitHub actor: ${githubActor ? `${githubActor}${githubActorRole ? ` (${githubActorRole})` : ""}` : "none"}`,
|
|
8529
|
+
`- Decided by: ${stringField3(context, "decidedBy") ?? "unknown"}`,
|
|
8530
|
+
`- Dispatched by: ${stringField3(context, "dispatchedBy") ?? "unknown"}`,
|
|
8531
|
+
`- Target: ${target ?? "none"}`
|
|
8532
|
+
];
|
|
8533
|
+
}
|
|
8534
|
+
function dispatchTargetLabel(target) {
|
|
8535
|
+
const type = stringField3(target, "type");
|
|
8536
|
+
const id = stringField3(target, "id");
|
|
8537
|
+
if (type && id) return `${type} ${id}`;
|
|
8538
|
+
return id ?? type;
|
|
8539
|
+
}
|
|
8402
8540
|
function artifactMarkdown(artifacts) {
|
|
8403
8541
|
if (artifacts.length === 0) return ["- none"];
|
|
8404
8542
|
return artifacts.map((artifact) => {
|
|
@@ -10445,10 +10583,9 @@ var init_dispatchClassified = __esm({
|
|
|
10445
10583
|
|
|
10446
10584
|
// src/jobIdentity.ts
|
|
10447
10585
|
function stableJobKey(job) {
|
|
10448
|
-
const capability = job.capability ?? job.action;
|
|
10586
|
+
const capability = job.workflow ?? job.capability ?? job.action;
|
|
10449
10587
|
const executable = job.executable ?? capability ?? "unknown";
|
|
10450
|
-
if (job.flavor === "scheduled" && job.capability)
|
|
10451
|
-
return `scheduled:${job.capability}:${executable}`;
|
|
10588
|
+
if (job.flavor === "scheduled" && job.capability) return `scheduled:${job.capability}:${executable}`;
|
|
10452
10589
|
const target = typeof job.target === "number" ? job.target : targetFromCliArgs(job.cliArgs);
|
|
10453
10590
|
const work = capability && executable && executable !== capability ? `${capability}:${executable}` : capability ?? executable;
|
|
10454
10591
|
return target === void 0 ? `${job.flavor}:${work}` : `${job.flavor}:${work}:${target}`;
|
|
@@ -16623,14 +16760,16 @@ function jobReferenceBlock(profileName, profile, data) {
|
|
|
16623
16760
|
const jobId = typeof data.jobId === "string" && data.jobId.length > 0 ? data.jobId : null;
|
|
16624
16761
|
const flavor = typeof data.jobFlavor === "string" && data.jobFlavor.length > 0 ? data.jobFlavor : null;
|
|
16625
16762
|
const schedule = typeof data.jobSchedule === "string" && data.jobSchedule.length > 0 ? data.jobSchedule : null;
|
|
16626
|
-
const isJob2 = Boolean(
|
|
16627
|
-
jobId || flavor || schedule || data.jobCapability || data.jobExecutable || data.jobWhy
|
|
16628
|
-
);
|
|
16763
|
+
const isJob2 = Boolean(jobId || flavor || schedule || data.jobCapability || data.jobExecutable || data.jobWhy);
|
|
16629
16764
|
if (!isJob2) return null;
|
|
16630
16765
|
const capability = typeof data.jobCapability === "string" && data.jobCapability.length > 0 ? data.jobCapability : profile.executable ? profile.name : null;
|
|
16631
16766
|
const executable = typeof profile.executable === "string" && profile.executable.length > 0 ? profile.executable : typeof data.jobExecutable === "string" && data.jobExecutable.length > 0 ? data.jobExecutable : profileName;
|
|
16632
16767
|
const agent = typeof profile.agent === "string" && profile.agent.length > 0 ? profile.agent : typeof data.jobAgent === "string" && data.jobAgent.length > 0 ? data.jobAgent : null;
|
|
16633
16768
|
const description = profile.describe.trim();
|
|
16769
|
+
const workflow = typeof data.workflowCapability === "string" && data.workflowCapability.length > 0 ? data.workflowCapability : null;
|
|
16770
|
+
const workflowStep = typeof data.workflowStep === "string" && data.workflowStep.length > 0 ? data.workflowStep : null;
|
|
16771
|
+
const workflowStepIndex = typeof data.workflowStepIndex === "number" && Number.isFinite(data.workflowStepIndex) ? data.workflowStepIndex : null;
|
|
16772
|
+
const workflowStepCount = typeof data.workflowStepCount === "number" && Number.isFinite(data.workflowStepCount) ? data.workflowStepCount : null;
|
|
16634
16773
|
const lines = [
|
|
16635
16774
|
"## Job reference",
|
|
16636
16775
|
"",
|
|
@@ -16642,7 +16781,9 @@ function jobReferenceBlock(profileName, profile, data) {
|
|
|
16642
16781
|
`- Capability: ${capability ?? "(none)"}`,
|
|
16643
16782
|
`- Executable: ${executable}`,
|
|
16644
16783
|
`- Agent: ${agent ?? "(none)"}`,
|
|
16645
|
-
`- Description: ${description || "(none)"}
|
|
16784
|
+
`- Description: ${description || "(none)"}`,
|
|
16785
|
+
...workflow ? [`- Workflow: ${workflow}`] : [],
|
|
16786
|
+
...workflowStep ? [`- Workflow step: ${workflowStepIndex ?? "?"}/${workflowStepCount ?? "?"} ${workflowStep}`] : []
|
|
16646
16787
|
];
|
|
16647
16788
|
return lines.join("\n");
|
|
16648
16789
|
}
|
|
@@ -17057,7 +17198,7 @@ async function runExecutableChain(profileName, input) {
|
|
|
17057
17198
|
};
|
|
17058
17199
|
}
|
|
17059
17200
|
process.stdout.write(
|
|
17060
|
-
`\u2192 kody: in-process return \u2192 ${afterJob.action ?? afterJob.capability} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
17201
|
+
`\u2192 kody: in-process return \u2192 ${afterJob.action ?? afterJob.capability ?? afterJob.workflow} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
17061
17202
|
|
|
17062
17203
|
`
|
|
17063
17204
|
);
|
|
@@ -17091,7 +17232,7 @@ async function runExecutableChain(profileName, input) {
|
|
|
17091
17232
|
};
|
|
17092
17233
|
}
|
|
17093
17234
|
process.stdout.write(
|
|
17094
|
-
`\u2192 kody: in-process hand-off \u2192 ${nextJob.action ?? nextJob.capability} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
17235
|
+
`\u2192 kody: in-process hand-off \u2192 ${nextJob.action ?? nextJob.capability ?? nextJob.workflow} (hop ${hops}/${MAX_CHAIN_HOPS})
|
|
17095
17236
|
|
|
17096
17237
|
`
|
|
17097
17238
|
);
|
|
@@ -17109,18 +17250,19 @@ async function runExecutableChain(profileName, input) {
|
|
|
17109
17250
|
};
|
|
17110
17251
|
}
|
|
17111
17252
|
if (result.nextDispatch || result.nextJob) {
|
|
17112
|
-
const pending = result.nextDispatch?.executable ?? result.nextJob?.executable ?? result.nextJob?.capability ?? "unknown";
|
|
17253
|
+
const pending = result.nextDispatch?.executable ?? result.nextDispatch?.workflow ?? result.nextJob?.executable ?? result.nextJob?.workflow ?? result.nextJob?.capability ?? "unknown";
|
|
17113
17254
|
process.stderr.write(`[kody] in-process hand-off cap (${MAX_CHAIN_HOPS}) reached; not running ${pending}
|
|
17114
17255
|
`);
|
|
17115
17256
|
}
|
|
17116
17257
|
return result;
|
|
17117
17258
|
}
|
|
17118
17259
|
function handoffToJob(handoff) {
|
|
17119
|
-
const dutyOrAction = handoff.action ?? handoff.capability;
|
|
17260
|
+
const dutyOrAction = handoff.workflow ?? handoff.action ?? handoff.capability;
|
|
17120
17261
|
if (!dutyOrAction) return null;
|
|
17121
17262
|
return {
|
|
17122
17263
|
action: handoff.action ?? handoff.capability,
|
|
17123
17264
|
capability: handoff.capability,
|
|
17265
|
+
workflow: handoff.workflow,
|
|
17124
17266
|
executable: handoff.executable,
|
|
17125
17267
|
cliArgs: handoff.cliArgs,
|
|
17126
17268
|
flavor: "instant",
|
|
@@ -17372,9 +17514,9 @@ var init_executor = __esm({
|
|
|
17372
17514
|
"src/executor.ts"() {
|
|
17373
17515
|
"use strict";
|
|
17374
17516
|
init_agent();
|
|
17517
|
+
init_agents();
|
|
17375
17518
|
init_capabilityReport();
|
|
17376
17519
|
init_capabilityResult();
|
|
17377
|
-
init_agents();
|
|
17378
17520
|
init_config();
|
|
17379
17521
|
init_container();
|
|
17380
17522
|
init_discipline();
|
|
@@ -17401,6 +17543,99 @@ var init_executor = __esm({
|
|
|
17401
17543
|
}
|
|
17402
17544
|
});
|
|
17403
17545
|
|
|
17546
|
+
// src/workflowDefinitions.ts
|
|
17547
|
+
import * as fs44 from "fs";
|
|
17548
|
+
import * as path42 from "path";
|
|
17549
|
+
function isWorkflowDefinitionId(value) {
|
|
17550
|
+
return WORKFLOW_ID_PATTERN.test(value);
|
|
17551
|
+
}
|
|
17552
|
+
function workflowDefinitionPath(id) {
|
|
17553
|
+
if (!isWorkflowDefinitionId(id)) {
|
|
17554
|
+
throw new Error(`Invalid workflow id "${id}"`);
|
|
17555
|
+
}
|
|
17556
|
+
return `workflows/${id}/workflow.json`;
|
|
17557
|
+
}
|
|
17558
|
+
function normalizeWorkflowDefinition(value) {
|
|
17559
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
17560
|
+
const raw = value;
|
|
17561
|
+
const name = typeof raw.name === "string" ? raw.name.trim() : "";
|
|
17562
|
+
const instructions = typeof raw.instructions === "string" ? raw.instructions.trim() : "";
|
|
17563
|
+
const capabilities = normalizeWorkflowCapabilities(raw.capabilities);
|
|
17564
|
+
if (!name || !instructions || capabilities.length === 0) return null;
|
|
17565
|
+
return {
|
|
17566
|
+
version: 1,
|
|
17567
|
+
name,
|
|
17568
|
+
instructions,
|
|
17569
|
+
capabilities,
|
|
17570
|
+
...typeof raw.createdAt === "string" ? { createdAt: raw.createdAt } : {},
|
|
17571
|
+
...typeof raw.updatedAt === "string" ? { updatedAt: raw.updatedAt } : {}
|
|
17572
|
+
};
|
|
17573
|
+
}
|
|
17574
|
+
function readWorkflowDefinition(config, cwd, id) {
|
|
17575
|
+
const file = readStateText(config, cwd, workflowDefinitionPath(id));
|
|
17576
|
+
if (!file) return readCompanyStoreWorkflowDefinition(id);
|
|
17577
|
+
return parseWorkflowDefinition(file.content);
|
|
17578
|
+
}
|
|
17579
|
+
function workflowDefinitionToCapabilityFolder(id, workflow, source = workflowDefinitionPath(id)) {
|
|
17580
|
+
return {
|
|
17581
|
+
slug: id,
|
|
17582
|
+
dir: path42.dirname(source),
|
|
17583
|
+
profilePath: source,
|
|
17584
|
+
bodyPath: source,
|
|
17585
|
+
title: workflow.name,
|
|
17586
|
+
body: workflow.instructions,
|
|
17587
|
+
rawBody: workflow.instructions,
|
|
17588
|
+
rawProfile: { name: id, workflow },
|
|
17589
|
+
config: {
|
|
17590
|
+
action: id,
|
|
17591
|
+
workflow: workflowDefinitionToConfig(workflow),
|
|
17592
|
+
describe: workflow.instructions
|
|
17593
|
+
}
|
|
17594
|
+
};
|
|
17595
|
+
}
|
|
17596
|
+
function normalizeWorkflowCapabilities(value) {
|
|
17597
|
+
if (!Array.isArray(value)) return [];
|
|
17598
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17599
|
+
const capabilities = [];
|
|
17600
|
+
for (const item of value) {
|
|
17601
|
+
if (typeof item !== "string") continue;
|
|
17602
|
+
const slug2 = item.trim();
|
|
17603
|
+
if (!CAPABILITY_ID_PATTERN.test(slug2) || seen.has(slug2)) continue;
|
|
17604
|
+
seen.add(slug2);
|
|
17605
|
+
capabilities.push(slug2);
|
|
17606
|
+
}
|
|
17607
|
+
return capabilities;
|
|
17608
|
+
}
|
|
17609
|
+
function workflowDefinitionToConfig(workflow) {
|
|
17610
|
+
return {
|
|
17611
|
+
steps: workflow.capabilities.map((capability) => ({ capability }))
|
|
17612
|
+
};
|
|
17613
|
+
}
|
|
17614
|
+
function readCompanyStoreWorkflowDefinition(id) {
|
|
17615
|
+
const root = getCompanyStoreAssetRoot("workflows");
|
|
17616
|
+
if (!root) return null;
|
|
17617
|
+
const filePath = path42.join(root, id, "workflow.json");
|
|
17618
|
+
if (!fs44.existsSync(filePath)) return null;
|
|
17619
|
+
return parseWorkflowDefinition(fs44.readFileSync(filePath, "utf8"));
|
|
17620
|
+
}
|
|
17621
|
+
function parseWorkflowDefinition(content) {
|
|
17622
|
+
try {
|
|
17623
|
+
return normalizeWorkflowDefinition(JSON.parse(content));
|
|
17624
|
+
} catch {
|
|
17625
|
+
return null;
|
|
17626
|
+
}
|
|
17627
|
+
}
|
|
17628
|
+
var WORKFLOW_ID_PATTERN, CAPABILITY_ID_PATTERN;
|
|
17629
|
+
var init_workflowDefinitions = __esm({
|
|
17630
|
+
"src/workflowDefinitions.ts"() {
|
|
17631
|
+
"use strict";
|
|
17632
|
+
init_companyStore();
|
|
17633
|
+
init_stateRepo();
|
|
17634
|
+
WORKFLOW_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,79}$/;
|
|
17635
|
+
CAPABILITY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$/;
|
|
17636
|
+
}
|
|
17637
|
+
});
|
|
17638
|
+
|
|
17404
17639
|
// src/job.ts
|
|
17405
17640
|
var job_exports = {};
|
|
17406
17641
|
__export(job_exports, {
|
|
@@ -17413,7 +17648,7 @@ __export(job_exports, {
|
|
|
17413
17648
|
stableJobKey: () => stableJobKey,
|
|
17414
17649
|
validateJob: () => validateJob
|
|
17415
17650
|
});
|
|
17416
|
-
import * as
|
|
17651
|
+
import * as path43 from "path";
|
|
17417
17652
|
function newJobId(flavor) {
|
|
17418
17653
|
localJobSeq += 1;
|
|
17419
17654
|
const runId = process.env.GITHUB_RUN_ID;
|
|
@@ -17425,8 +17660,8 @@ function validateJob(input) {
|
|
|
17425
17660
|
throw new InvalidJobError("job must be an object");
|
|
17426
17661
|
}
|
|
17427
17662
|
const j = input;
|
|
17428
|
-
if (typeof j.capability !== "string" && typeof j.action !== "string") {
|
|
17429
|
-
throw new InvalidJobError("job must reference a capability action or
|
|
17663
|
+
if (typeof j.capability !== "string" && typeof j.action !== "string" && typeof j.workflow !== "string") {
|
|
17664
|
+
throw new InvalidJobError("job must reference a capability action, capability, or workflow");
|
|
17430
17665
|
}
|
|
17431
17666
|
if (j.flavor !== "instant" && j.flavor !== "scheduled") {
|
|
17432
17667
|
throw new InvalidJobError(`job.flavor must be "instant" or "scheduled" (got ${String(j.flavor)})`);
|
|
@@ -17438,6 +17673,7 @@ function validateJob(input) {
|
|
|
17438
17673
|
action: typeof j.action === "string" ? j.action : void 0,
|
|
17439
17674
|
executable: typeof j.executable === "string" ? j.executable : void 0,
|
|
17440
17675
|
capability: typeof j.capability === "string" ? j.capability : void 0,
|
|
17676
|
+
workflow: typeof j.workflow === "string" ? j.workflow : void 0,
|
|
17441
17677
|
why: typeof j.why === "string" ? j.why : void 0,
|
|
17442
17678
|
agent: typeof j.agent === "string" ? j.agent : void 0,
|
|
17443
17679
|
schedule: typeof j.schedule === "string" ? j.schedule : void 0,
|
|
@@ -17451,21 +17687,49 @@ function validateJob(input) {
|
|
|
17451
17687
|
async function runJob(job, base) {
|
|
17452
17688
|
const valid = validateJob(job);
|
|
17453
17689
|
const action = valid.action ?? valid.capability;
|
|
17454
|
-
const projectCapabilitiesRoot =
|
|
17455
|
-
const resolvedCapability = action ? resolveCapabilityAction(action, projectCapabilitiesRoot) : null;
|
|
17690
|
+
const projectCapabilitiesRoot = path43.join(base.cwd, ".kody", "capabilities");
|
|
17691
|
+
const resolvedCapability = !valid.workflow && action ? resolveCapabilityAction(action, projectCapabilitiesRoot) : null;
|
|
17456
17692
|
const capabilityIdentity = valid.capability ?? resolvedCapability?.capability;
|
|
17457
|
-
const capabilityContext = loadCapabilityContext(capabilityIdentity, base.cwd);
|
|
17693
|
+
const capabilityContext = valid.workflow ? null : loadCapabilityContext(capabilityIdentity, base.cwd);
|
|
17694
|
+
const workflowContext = valid.workflow ? loadWorkflowContext(valid.workflow, base) : !capabilityContext && !resolvedCapability ? loadWorkflowContext(capabilityIdentity ?? action, base) : null;
|
|
17458
17695
|
const explicitExecutableOnly = valid.executable !== void 0 && (valid.action === void 0 || valid.action === valid.executable) && (valid.capability === void 0 || valid.capability === valid.executable);
|
|
17459
|
-
if (!resolvedCapability && !capabilityContext && !explicitExecutableOnly) {
|
|
17460
|
-
throw new InvalidJobError(
|
|
17696
|
+
if (!resolvedCapability && !capabilityContext && !workflowContext && !explicitExecutableOnly) {
|
|
17697
|
+
throw new InvalidJobError(
|
|
17698
|
+
`job capability/workflow not found: ${valid.workflow ?? action ?? valid.capability ?? "<none>"}`
|
|
17699
|
+
);
|
|
17461
17700
|
}
|
|
17701
|
+
const workflow = capabilityContext?.config.workflow ?? workflowContext?.config.workflow;
|
|
17702
|
+
const workflowIdentity = valid.workflow ?? capabilityIdentity ?? workflowContext?.slug;
|
|
17462
17703
|
const capabilitySelectedExecutable = resolvedCapability?.executable ?? capabilityContext?.config.executable ?? capabilityContext?.config.executables?.[0] ?? (capabilityContext?.config.tickScript ? "capability-tick-scripted" : void 0);
|
|
17463
17704
|
const profileName = valid.executable ?? capabilitySelectedExecutable;
|
|
17464
|
-
if (
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
);
|
|
17705
|
+
if (workflow && shouldRunCapabilityWorkflow(valid, workflow, workflowIdentity, capabilitySelectedExecutable, base)) {
|
|
17706
|
+
const workflowCapability = capabilityContext ?? workflowContext;
|
|
17707
|
+
const workflowJob = workflowContext && !valid.why ? { ...valid, why: workflowContext.body } : valid;
|
|
17708
|
+
return runCapabilityWorkflow(workflowJob, workflow, workflowCapability, base);
|
|
17468
17709
|
}
|
|
17710
|
+
if (!profileName) {
|
|
17711
|
+
throw new InvalidJobError(`job capability resolves to no executable: ${capabilityIdentity ?? action}`);
|
|
17712
|
+
}
|
|
17713
|
+
return runDefaultCapabilityWorkflow(
|
|
17714
|
+
valid,
|
|
17715
|
+
profileName,
|
|
17716
|
+
capabilityIdentity,
|
|
17717
|
+
capabilityContext,
|
|
17718
|
+
resolvedCapability,
|
|
17719
|
+
base
|
|
17720
|
+
);
|
|
17721
|
+
}
|
|
17722
|
+
async function runDefaultCapabilityWorkflow(job, profileName, capabilityIdentity, capabilityContext, resolvedCapability, base) {
|
|
17723
|
+
return runCapabilityImplementationStep(
|
|
17724
|
+
job,
|
|
17725
|
+
profileName,
|
|
17726
|
+
capabilityIdentity,
|
|
17727
|
+
capabilityContext,
|
|
17728
|
+
resolvedCapability,
|
|
17729
|
+
base
|
|
17730
|
+
);
|
|
17731
|
+
}
|
|
17732
|
+
async function runCapabilityImplementationStep(valid, profileName, capabilityIdentity, capabilityContext, resolvedCapability, base) {
|
|
17469
17733
|
const preloadedData = { ...base.preloadedData ?? {} };
|
|
17470
17734
|
preloadedData.jobId = newJobId(valid.flavor);
|
|
17471
17735
|
preloadedData.jobKey = stableJobKey(valid);
|
|
@@ -17474,9 +17738,7 @@ async function runJob(job, base) {
|
|
|
17474
17738
|
if (valid.action !== void 0 && valid.action.length > 0) preloadedData.jobAction = valid.action;
|
|
17475
17739
|
if (capabilityIdentity !== void 0 && capabilityIdentity.length > 0)
|
|
17476
17740
|
preloadedData.jobCapability = capabilityIdentity;
|
|
17477
|
-
|
|
17478
|
-
if (executableIdentity !== void 0 && executableIdentity.length > 0)
|
|
17479
|
-
preloadedData.jobExecutable = executableIdentity;
|
|
17741
|
+
preloadedData.jobExecutable = profileName;
|
|
17480
17742
|
if (valid.schedule !== void 0 && valid.schedule.length > 0) preloadedData.jobSchedule = valid.schedule;
|
|
17481
17743
|
if (valid.saveReport === true) preloadedData.jobSaveReport = true;
|
|
17482
17744
|
if (capabilityContext) {
|
|
@@ -17484,8 +17746,7 @@ async function runJob(job, base) {
|
|
|
17484
17746
|
preloadedData.capabilityTitle = capabilityContext.title;
|
|
17485
17747
|
preloadedData.dutyIntent = capabilityContext.body;
|
|
17486
17748
|
preloadedData.jobIntent = capabilityContext.body;
|
|
17487
|
-
if (preloadedData.jobCapability === void 0)
|
|
17488
|
-
preloadedData.jobCapability = capabilityContext.slug;
|
|
17749
|
+
if (preloadedData.jobCapability === void 0) preloadedData.jobCapability = capabilityContext.slug;
|
|
17489
17750
|
if (capabilityContext.config.agent && preloadedData.jobAgent === void 0) {
|
|
17490
17751
|
preloadedData.jobAgent = capabilityContext.config.agent;
|
|
17491
17752
|
}
|
|
@@ -17509,9 +17770,182 @@ async function runJob(job, base) {
|
|
|
17509
17770
|
const run = base.chain === false ? runExecutable : runExecutableChain;
|
|
17510
17771
|
return run(profileName, input);
|
|
17511
17772
|
}
|
|
17773
|
+
function shouldRunCapabilityWorkflow(job, workflow, capabilityIdentity, selectedExecutable, base) {
|
|
17774
|
+
if (workflow.steps.length === 0) return false;
|
|
17775
|
+
if (!capabilityIdentity) return false;
|
|
17776
|
+
const stack = Array.isArray(base.preloadedData?.workflowStack) ? base.preloadedData.workflowStack.filter((entry) => typeof entry === "string") : [];
|
|
17777
|
+
if (stack.includes(capabilityIdentity)) return false;
|
|
17778
|
+
if (!job.executable) return true;
|
|
17779
|
+
return job.executable === selectedExecutable || job.executable === capabilityIdentity || job.executable === job.action;
|
|
17780
|
+
}
|
|
17781
|
+
async function runCapabilityWorkflow(parent, workflow, capability, base) {
|
|
17782
|
+
let chainData = {
|
|
17783
|
+
...base.preloadedData ?? {},
|
|
17784
|
+
workflowCapability: capability.slug,
|
|
17785
|
+
workflowTitle: capability.title,
|
|
17786
|
+
workflowStepCount: workflow.steps.length,
|
|
17787
|
+
workflowIssueNumber: workflowIssueNumber(parent),
|
|
17788
|
+
workflowStack: [
|
|
17789
|
+
...Array.isArray(base.preloadedData?.workflowStack) ? base.preloadedData.workflowStack.filter((entry) => typeof entry === "string") : [],
|
|
17790
|
+
capability.slug
|
|
17791
|
+
]
|
|
17792
|
+
};
|
|
17793
|
+
let result = { exitCode: 0 };
|
|
17794
|
+
for (let index = 0; index < workflow.steps.length; index++) {
|
|
17795
|
+
const step = workflow.steps[index];
|
|
17796
|
+
const label = step.action ?? step.capability;
|
|
17797
|
+
if (!shouldRunWorkflowStep(step, chainData)) {
|
|
17798
|
+
process.stdout.write(
|
|
17799
|
+
`\u2192 kody: workflow ${capability.slug} step ${index + 1}/${workflow.steps.length} \u2192 ${label} (skipped)
|
|
17800
|
+
|
|
17801
|
+
`
|
|
17802
|
+
);
|
|
17803
|
+
continue;
|
|
17804
|
+
}
|
|
17805
|
+
const child = workflowStepToJob(step, parent, chainData);
|
|
17806
|
+
process.stdout.write(
|
|
17807
|
+
`\u2192 kody: workflow ${capability.slug} step ${index + 1}/${workflow.steps.length} \u2192 ${label}
|
|
17808
|
+
|
|
17809
|
+
`
|
|
17810
|
+
);
|
|
17811
|
+
result = await runJob(child, {
|
|
17812
|
+
...base,
|
|
17813
|
+
preloadedData: {
|
|
17814
|
+
...chainData,
|
|
17815
|
+
workflowStep: label,
|
|
17816
|
+
workflowStepIndex: index + 1,
|
|
17817
|
+
workflowStepReason: step.reason
|
|
17818
|
+
}
|
|
17819
|
+
});
|
|
17820
|
+
const outcome = workflowOutcome(result);
|
|
17821
|
+
const prUrl = result.taskState?.core.prUrl ?? (typeof chainData.workflowPrUrl === "string" ? chainData.workflowPrUrl : void 0);
|
|
17822
|
+
chainData = {
|
|
17823
|
+
...chainData,
|
|
17824
|
+
...result.taskState ? { taskState: result.taskState } : {},
|
|
17825
|
+
...outcome ? { workflowLastOutcome: outcome } : {},
|
|
17826
|
+
...prUrl ? { workflowPrUrl: prUrl } : {},
|
|
17827
|
+
...parsePrNumber5(prUrl) ? { workflowPrNumber: parsePrNumber5(prUrl) } : {}
|
|
17828
|
+
};
|
|
17829
|
+
if (result.exitCode !== 0 && !canContinueWorkflow(step, outcome)) {
|
|
17830
|
+
return {
|
|
17831
|
+
...result,
|
|
17832
|
+
reason: result.reason ?? `workflow ${capability.slug} stopped at step ${index + 1}/${workflow.steps.length}: ${label}`
|
|
17833
|
+
};
|
|
17834
|
+
}
|
|
17835
|
+
}
|
|
17836
|
+
return result;
|
|
17837
|
+
}
|
|
17838
|
+
function workflowStepToJob(step, parent, chainData) {
|
|
17839
|
+
const action = step.action ?? step.capability;
|
|
17840
|
+
const rawArgs = {
|
|
17841
|
+
...parent.cliArgs,
|
|
17842
|
+
...step.cliArgs ?? {}
|
|
17843
|
+
};
|
|
17844
|
+
const targetNumber = workflowStepTargetNumber(step, parent, chainData);
|
|
17845
|
+
if (step.target === "pr") {
|
|
17846
|
+
if (typeof targetNumber !== "number") {
|
|
17847
|
+
throw new InvalidJobError(`workflow step ${action} needs a PR target but no prior PR URL is available`);
|
|
17848
|
+
}
|
|
17849
|
+
rawArgs.pr = targetNumber;
|
|
17850
|
+
} else if (step.target === "issue" && typeof targetNumber === "number") {
|
|
17851
|
+
rawArgs.issue = targetNumber;
|
|
17852
|
+
}
|
|
17853
|
+
const cliArgs = filterCliArgsForStep(action, rawArgs);
|
|
17854
|
+
const target = typeof targetNumber === "number" ? targetNumber : typeof parent.target === "number" ? parent.target : targetFromCliArgs(cliArgs);
|
|
17855
|
+
return {
|
|
17856
|
+
action,
|
|
17857
|
+
capability: step.capability,
|
|
17858
|
+
...step.executable ? { executable: step.executable } : {},
|
|
17859
|
+
...composeStepWhy(parent.why, step) ? { why: composeStepWhy(parent.why, step) } : {},
|
|
17860
|
+
...step.agent ?? parent.agent ? { agent: step.agent ?? parent.agent } : {},
|
|
17861
|
+
...parent.schedule ? { schedule: parent.schedule } : {},
|
|
17862
|
+
...typeof target === "number" ? { target } : {},
|
|
17863
|
+
cliArgs,
|
|
17864
|
+
flavor: parent.flavor,
|
|
17865
|
+
force: parent.force,
|
|
17866
|
+
saveReport: step.saveReport === true || parent.saveReport === true
|
|
17867
|
+
};
|
|
17868
|
+
}
|
|
17869
|
+
function shouldRunWorkflowStep(step, data) {
|
|
17870
|
+
if (!step.runWhen) return true;
|
|
17871
|
+
const context = workflowConditionContext(data);
|
|
17872
|
+
return Object.entries(step.runWhen).every(
|
|
17873
|
+
([path49, expected]) => valueMatches(resolveDottedPath2(context, path49), expected)
|
|
17874
|
+
);
|
|
17875
|
+
}
|
|
17876
|
+
function canContinueWorkflow(step, outcome) {
|
|
17877
|
+
if (!outcome || !step.continueOn || step.continueOn.length === 0) return false;
|
|
17878
|
+
return step.continueOn.includes(outcome.type);
|
|
17879
|
+
}
|
|
17880
|
+
function workflowOutcome(result) {
|
|
17881
|
+
return result.taskState?.core.lastOutcome ?? null;
|
|
17882
|
+
}
|
|
17883
|
+
function workflowConditionContext(data) {
|
|
17884
|
+
const lastOutcome = data.workflowLastOutcome;
|
|
17885
|
+
return {
|
|
17886
|
+
...data,
|
|
17887
|
+
workflow: {
|
|
17888
|
+
lastOutcome,
|
|
17889
|
+
issueNumber: data.workflowIssueNumber,
|
|
17890
|
+
prNumber: data.workflowPrNumber,
|
|
17891
|
+
prUrl: data.workflowPrUrl
|
|
17892
|
+
},
|
|
17893
|
+
lastOutcome
|
|
17894
|
+
};
|
|
17895
|
+
}
|
|
17896
|
+
function resolveDottedPath2(root, dotted) {
|
|
17897
|
+
return dotted.split(".").reduce((cur, part) => {
|
|
17898
|
+
if (!cur || typeof cur !== "object") return void 0;
|
|
17899
|
+
return cur[part];
|
|
17900
|
+
}, root);
|
|
17901
|
+
}
|
|
17902
|
+
function valueMatches(actual, expected) {
|
|
17903
|
+
if (Array.isArray(expected)) return expected.some((entry) => valueMatches(actual, entry));
|
|
17904
|
+
return actual === expected;
|
|
17905
|
+
}
|
|
17906
|
+
function workflowStepTargetNumber(step, parent, chainData) {
|
|
17907
|
+
if (step.target === "pr") return workflowPrNumber(chainData) ?? targetFromCliArgs(step.cliArgs ?? {});
|
|
17908
|
+
if (step.target === "issue") return workflowIssueNumber(parent);
|
|
17909
|
+
return typeof parent.target === "number" ? parent.target : targetFromCliArgs({ ...parent.cliArgs, ...step.cliArgs ?? {} });
|
|
17910
|
+
}
|
|
17911
|
+
function workflowIssueNumber(parent) {
|
|
17912
|
+
return typeof parent.target === "number" ? parent.target : targetFromCliArgs(parent.cliArgs);
|
|
17913
|
+
}
|
|
17914
|
+
function workflowPrNumber(data) {
|
|
17915
|
+
if (typeof data.workflowPrNumber === "number" && Number.isFinite(data.workflowPrNumber)) return data.workflowPrNumber;
|
|
17916
|
+
const prUrl = typeof data.workflowPrUrl === "string" ? data.workflowPrUrl : typeof data.taskState?.core?.prUrl === "string" ? data.taskState.core.prUrl : void 0;
|
|
17917
|
+
return parsePrNumber5(prUrl) ?? void 0;
|
|
17918
|
+
}
|
|
17919
|
+
function parsePrNumber5(url) {
|
|
17920
|
+
if (!url) return null;
|
|
17921
|
+
const m = url.match(/\/pull\/(\d+)(?:[/?#]|$)/);
|
|
17922
|
+
if (!m) return null;
|
|
17923
|
+
const n = parseInt(m[1], 10);
|
|
17924
|
+
return Number.isFinite(n) ? n : null;
|
|
17925
|
+
}
|
|
17926
|
+
function filterCliArgsForStep(action, raw) {
|
|
17927
|
+
const inputs = getCapabilityActionInputs(action);
|
|
17928
|
+
if (!inputs) return raw;
|
|
17929
|
+
const allowed = /* @__PURE__ */ new Set(["_", "cwd", "verbose", "quiet"]);
|
|
17930
|
+
for (const input of inputs) {
|
|
17931
|
+
const flagKey = input.flag.replace(/^--/, "");
|
|
17932
|
+
allowed.add(input.name);
|
|
17933
|
+
allowed.add(flagKey);
|
|
17934
|
+
if (flagKey.includes("-")) allowed.add(flagKey.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase()));
|
|
17935
|
+
}
|
|
17936
|
+
return Object.fromEntries(Object.entries(raw).filter(([key]) => allowed.has(key)));
|
|
17937
|
+
}
|
|
17938
|
+
function composeStepWhy(parentWhy, step) {
|
|
17939
|
+
return [parentWhy?.trim(), step.reason ? `Workflow step: ${step.reason}` : ""].filter((part) => Boolean(part)).join("\n\n");
|
|
17940
|
+
}
|
|
17512
17941
|
function loadCapabilityContext(slug2, cwd) {
|
|
17513
17942
|
if (!slug2) return null;
|
|
17514
|
-
return resolveCapabilityFolder(slug2,
|
|
17943
|
+
return resolveCapabilityFolder(slug2, path43.join(cwd, ".kody", "capabilities"));
|
|
17944
|
+
}
|
|
17945
|
+
function loadWorkflowContext(slug2, base) {
|
|
17946
|
+
if (!slug2 || !base.config || !isWorkflowDefinitionId(slug2)) return null;
|
|
17947
|
+
const workflow = readWorkflowDefinition(base.config, base.cwd, slug2);
|
|
17948
|
+
return workflow ? workflowDefinitionToCapabilityFolder(slug2, workflow) : null;
|
|
17515
17949
|
}
|
|
17516
17950
|
function mintInstantJob(dispatch2, opts) {
|
|
17517
17951
|
return {
|
|
@@ -17543,6 +17977,7 @@ var init_job = __esm({
|
|
|
17543
17977
|
"use strict";
|
|
17544
17978
|
init_executor();
|
|
17545
17979
|
init_registry();
|
|
17980
|
+
init_workflowDefinitions();
|
|
17546
17981
|
init_jobIdentity();
|
|
17547
17982
|
init_jobIdentity();
|
|
17548
17983
|
DEFAULT_INSTANT_AGENT = "kody";
|
|
@@ -17663,9 +18098,9 @@ function translateOpenAISseToBrain(opts) {
|
|
|
17663
18098
|
}
|
|
17664
18099
|
|
|
17665
18100
|
// src/servers/brain-serve.ts
|
|
17666
|
-
import * as
|
|
18101
|
+
import * as fs47 from "fs";
|
|
17667
18102
|
import { createServer } from "http";
|
|
17668
|
-
import * as
|
|
18103
|
+
import * as path46 from "path";
|
|
17669
18104
|
|
|
17670
18105
|
// src/chat/loop.ts
|
|
17671
18106
|
init_agent();
|
|
@@ -18225,8 +18660,8 @@ init_config();
|
|
|
18225
18660
|
|
|
18226
18661
|
// src/kody-cli.ts
|
|
18227
18662
|
import { execFileSync as execFileSync25 } from "child_process";
|
|
18228
|
-
import * as
|
|
18229
|
-
import * as
|
|
18663
|
+
import * as fs45 from "fs";
|
|
18664
|
+
import * as path44 from "path";
|
|
18230
18665
|
|
|
18231
18666
|
// src/app-auth.ts
|
|
18232
18667
|
import { createSign } from "crypto";
|
|
@@ -18847,9 +19282,9 @@ async function resolveAuthToken(env = process.env) {
|
|
|
18847
19282
|
return void 0;
|
|
18848
19283
|
}
|
|
18849
19284
|
function detectPackageManager2(cwd) {
|
|
18850
|
-
if (
|
|
18851
|
-
if (
|
|
18852
|
-
if (
|
|
19285
|
+
if (fs45.existsSync(path44.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
19286
|
+
if (fs45.existsSync(path44.join(cwd, "yarn.lock"))) return "yarn";
|
|
19287
|
+
if (fs45.existsSync(path44.join(cwd, "bun.lockb"))) return "bun";
|
|
18853
19288
|
return "npm";
|
|
18854
19289
|
}
|
|
18855
19290
|
function shouldChainScheduledWatch(match) {
|
|
@@ -18942,8 +19377,8 @@ function postFailureTail(issueNumber, cwd, reason) {
|
|
|
18942
19377
|
const logPath = lastRunLogPath(cwd);
|
|
18943
19378
|
let tail = "";
|
|
18944
19379
|
try {
|
|
18945
|
-
if (
|
|
18946
|
-
const content =
|
|
19380
|
+
if (fs45.existsSync(logPath)) {
|
|
19381
|
+
const content = fs45.readFileSync(logPath, "utf-8");
|
|
18947
19382
|
tail = content.slice(-3e3);
|
|
18948
19383
|
}
|
|
18949
19384
|
} catch {
|
|
@@ -18968,7 +19403,7 @@ async function runCi(argv) {
|
|
|
18968
19403
|
return 0;
|
|
18969
19404
|
}
|
|
18970
19405
|
const args = parseCiArgs(argv);
|
|
18971
|
-
const cwd = args.cwd ?
|
|
19406
|
+
const cwd = args.cwd ? path44.resolve(args.cwd) : process.cwd();
|
|
18972
19407
|
let earlyConfig;
|
|
18973
19408
|
let earlyConfigError;
|
|
18974
19409
|
try {
|
|
@@ -18983,9 +19418,9 @@ async function runCi(argv) {
|
|
|
18983
19418
|
let manualWorkflowDispatch = false;
|
|
18984
19419
|
let forceRunAction = null;
|
|
18985
19420
|
let forceRunCliArgs = {};
|
|
18986
|
-
if (!args.issueNumber && !autoFallback && eventName === "workflow_dispatch" && dispatchEventPath &&
|
|
19421
|
+
if (!args.issueNumber && !autoFallback && eventName === "workflow_dispatch" && dispatchEventPath && fs45.existsSync(dispatchEventPath)) {
|
|
18987
19422
|
try {
|
|
18988
|
-
const evt = JSON.parse(
|
|
19423
|
+
const evt = JSON.parse(fs45.readFileSync(dispatchEventPath, "utf-8"));
|
|
18989
19424
|
const issueInput = parseInt(String(evt?.inputs?.issue_number ?? ""), 10);
|
|
18990
19425
|
const sessionInput = String(evt?.inputs?.sessionId ?? "");
|
|
18991
19426
|
const dutyInput = String(evt?.inputs?.capability ?? evt?.inputs?.executable ?? "").trim();
|
|
@@ -19317,8 +19752,8 @@ init_repoWorkspace();
|
|
|
19317
19752
|
|
|
19318
19753
|
// src/scripts/brainTurnLog.ts
|
|
19319
19754
|
init_runtimePaths();
|
|
19320
|
-
import * as
|
|
19321
|
-
import * as
|
|
19755
|
+
import * as fs46 from "fs";
|
|
19756
|
+
import * as path45 from "path";
|
|
19322
19757
|
import posixPath4 from "path/posix";
|
|
19323
19758
|
var live = /* @__PURE__ */ new Map();
|
|
19324
19759
|
function brainEventsFilePath(dir, chatId) {
|
|
@@ -19329,8 +19764,8 @@ function brainEventsStatePath(chatId) {
|
|
|
19329
19764
|
}
|
|
19330
19765
|
function lastPersistedSeq(dir, chatId) {
|
|
19331
19766
|
const p = brainEventsFilePath(dir, chatId);
|
|
19332
|
-
if (!
|
|
19333
|
-
const lines =
|
|
19767
|
+
if (!fs46.existsSync(p)) return 0;
|
|
19768
|
+
const lines = fs46.readFileSync(p, "utf-8").split("\n").filter(Boolean);
|
|
19334
19769
|
if (lines.length === 0) return 0;
|
|
19335
19770
|
try {
|
|
19336
19771
|
return JSON.parse(lines[lines.length - 1]).seq || 0;
|
|
@@ -19340,9 +19775,9 @@ function lastPersistedSeq(dir, chatId) {
|
|
|
19340
19775
|
}
|
|
19341
19776
|
function readSince(dir, chatId, since) {
|
|
19342
19777
|
const p = brainEventsFilePath(dir, chatId);
|
|
19343
|
-
if (!
|
|
19778
|
+
if (!fs46.existsSync(p)) return [];
|
|
19344
19779
|
const out = [];
|
|
19345
|
-
for (const line of
|
|
19780
|
+
for (const line of fs46.readFileSync(p, "utf-8").split("\n")) {
|
|
19346
19781
|
if (!line) continue;
|
|
19347
19782
|
try {
|
|
19348
19783
|
const rec = JSON.parse(line);
|
|
@@ -19368,12 +19803,12 @@ function beginTurn(dir, chatId) {
|
|
|
19368
19803
|
};
|
|
19369
19804
|
live.set(chatId, state);
|
|
19370
19805
|
const p = brainEventsFilePath(dir, chatId);
|
|
19371
|
-
|
|
19806
|
+
fs46.mkdirSync(path45.dirname(p), { recursive: true });
|
|
19372
19807
|
return (event) => {
|
|
19373
19808
|
state.seq += 1;
|
|
19374
19809
|
const rec = { seq: state.seq, turn, ts: Date.now(), event };
|
|
19375
19810
|
try {
|
|
19376
|
-
|
|
19811
|
+
fs46.appendFileSync(p, `${JSON.stringify(rec)}
|
|
19377
19812
|
`);
|
|
19378
19813
|
} catch (err) {
|
|
19379
19814
|
process.stderr.write(
|
|
@@ -19412,7 +19847,7 @@ function endTurnIfUnterminated(dir, chatId, errMessage) {
|
|
|
19412
19847
|
event: { type: "error", error: errMessage || "turn ended unexpectedly", chatId }
|
|
19413
19848
|
};
|
|
19414
19849
|
try {
|
|
19415
|
-
|
|
19850
|
+
fs46.appendFileSync(brainEventsFilePath(dir, chatId), `${JSON.stringify(rec)}
|
|
19416
19851
|
`);
|
|
19417
19852
|
} catch {
|
|
19418
19853
|
}
|
|
@@ -19718,7 +20153,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
19718
20153
|
);
|
|
19719
20154
|
}
|
|
19720
20155
|
}
|
|
19721
|
-
|
|
20156
|
+
fs47.mkdirSync(path46.dirname(sessionFile), { recursive: true });
|
|
19722
20157
|
appendTurn(sessionFile, {
|
|
19723
20158
|
role: "user",
|
|
19724
20159
|
content: message,
|
|
@@ -19783,7 +20218,7 @@ async function handleChatTurn(req, res, chatId, opts) {
|
|
|
19783
20218
|
function buildServer(opts) {
|
|
19784
20219
|
const runTurn = opts.runTurn ?? runChatTurn;
|
|
19785
20220
|
const cloneRepo = opts.cloneRepo ?? defaultCloneRepo;
|
|
19786
|
-
const reposRoot = opts.reposRoot ??
|
|
20221
|
+
const reposRoot = opts.reposRoot ?? path46.join(path46.dirname(path46.resolve(opts.cwd)), "repos");
|
|
19787
20222
|
return createServer(async (req, res) => {
|
|
19788
20223
|
if (!req.method || !req.url) {
|
|
19789
20224
|
sendJson(res, 400, { error: "bad request" });
|
|
@@ -20378,8 +20813,8 @@ async function loadConfigSafe() {
|
|
|
20378
20813
|
}
|
|
20379
20814
|
|
|
20380
20815
|
// src/chat-cli.ts
|
|
20381
|
-
import * as
|
|
20382
|
-
import * as
|
|
20816
|
+
import * as fs49 from "fs";
|
|
20817
|
+
import * as path48 from "path";
|
|
20383
20818
|
|
|
20384
20819
|
// src/chat/inbox.ts
|
|
20385
20820
|
import { execFileSync as execFileSync26 } from "child_process";
|
|
@@ -20451,8 +20886,8 @@ function currentBranch(cwd) {
|
|
|
20451
20886
|
|
|
20452
20887
|
// src/chat/state-sync.ts
|
|
20453
20888
|
init_stateRepo();
|
|
20454
|
-
import * as
|
|
20455
|
-
import * as
|
|
20889
|
+
import * as fs48 from "fs";
|
|
20890
|
+
import * as path47 from "path";
|
|
20456
20891
|
function jsonlLines2(text) {
|
|
20457
20892
|
return text.split("\n").filter((line) => line.length > 0);
|
|
20458
20893
|
}
|
|
@@ -20469,15 +20904,15 @@ function mergeJsonl2(localText, remoteText) {
|
|
|
20469
20904
|
function syncJsonlFileFromState(opts) {
|
|
20470
20905
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
20471
20906
|
if (!remote) return;
|
|
20472
|
-
const local =
|
|
20907
|
+
const local = fs48.existsSync(opts.localPath) ? fs48.readFileSync(opts.localPath, "utf-8") : "";
|
|
20473
20908
|
const next = mergeJsonl2(local, remote.content);
|
|
20474
20909
|
if (next === local) return;
|
|
20475
|
-
|
|
20476
|
-
|
|
20910
|
+
fs48.mkdirSync(path47.dirname(opts.localPath), { recursive: true });
|
|
20911
|
+
fs48.writeFileSync(opts.localPath, next);
|
|
20477
20912
|
}
|
|
20478
20913
|
function persistJsonlFileToState(opts) {
|
|
20479
|
-
if (!
|
|
20480
|
-
const localText =
|
|
20914
|
+
if (!fs48.existsSync(opts.localPath)) return;
|
|
20915
|
+
const localText = fs48.readFileSync(opts.localPath, "utf-8");
|
|
20481
20916
|
for (let attempt = 1; attempt <= 3; attempt += 1) {
|
|
20482
20917
|
const remote = readStateText(opts.config, opts.cwd, opts.statePath);
|
|
20483
20918
|
const body = mergeJsonl2(localText, remote?.content ?? "");
|
|
@@ -20737,7 +21172,7 @@ async function runChat(argv) {
|
|
|
20737
21172
|
${CHAT_HELP}`);
|
|
20738
21173
|
return 64;
|
|
20739
21174
|
}
|
|
20740
|
-
const cwd = args.cwd ?
|
|
21175
|
+
const cwd = args.cwd ? path48.resolve(args.cwd) : process.cwd();
|
|
20741
21176
|
const sessionId = args.sessionId;
|
|
20742
21177
|
const unpackedSecrets = unpackAllSecrets();
|
|
20743
21178
|
if (unpackedSecrets > 0) {
|
|
@@ -20798,7 +21233,7 @@ ${CHAT_HELP}`);
|
|
|
20798
21233
|
const sink = buildSink(cwd, sessionId, args.dashboardUrl);
|
|
20799
21234
|
const meta = readMeta(sessionFile);
|
|
20800
21235
|
process.stdout.write(
|
|
20801
|
-
`\u2192 kody:chat: session file=${sessionFile} exists=${
|
|
21236
|
+
`\u2192 kody:chat: session file=${sessionFile} exists=${fs49.existsSync(sessionFile)} meta=${meta ? meta.mode : "none"}
|
|
20802
21237
|
`
|
|
20803
21238
|
);
|
|
20804
21239
|
try {
|
|
@@ -20958,8 +21393,8 @@ var FlyClient = class {
|
|
|
20958
21393
|
get fetch() {
|
|
20959
21394
|
return this.opts.fetchImpl ?? fetch;
|
|
20960
21395
|
}
|
|
20961
|
-
async call(
|
|
20962
|
-
const res = await this.fetch(`${FLY_API_BASE}${
|
|
21396
|
+
async call(path49, init = {}) {
|
|
21397
|
+
const res = await this.fetch(`${FLY_API_BASE}${path49}`, {
|
|
20963
21398
|
method: init.method ?? "GET",
|
|
20964
21399
|
headers: {
|
|
20965
21400
|
Authorization: `Bearer ${this.opts.token}`,
|
|
@@ -20970,7 +21405,7 @@ var FlyClient = class {
|
|
|
20970
21405
|
if (res.status === 404 && init.allow404) return null;
|
|
20971
21406
|
if (!res.ok) {
|
|
20972
21407
|
const text = await res.text().catch(() => "");
|
|
20973
|
-
throw new Error(`Fly API ${res.status} on ${
|
|
21408
|
+
throw new Error(`Fly API ${res.status} on ${path49}: ${text.slice(0, 200) || res.statusText}`);
|
|
20974
21409
|
}
|
|
20975
21410
|
if (res.status === 204) return null;
|
|
20976
21411
|
const raw = await res.text();
|
|
@@ -21685,7 +22120,7 @@ async function poolServe() {
|
|
|
21685
22120
|
|
|
21686
22121
|
// src/servers/runner-serve.ts
|
|
21687
22122
|
import { spawn as spawn8 } from "child_process";
|
|
21688
|
-
import * as
|
|
22123
|
+
import * as fs50 from "fs";
|
|
21689
22124
|
import { createServer as createServer5 } from "http";
|
|
21690
22125
|
var DEFAULT_PORT2 = 8080;
|
|
21691
22126
|
var DEFAULT_WORKDIR = "/workspace/repo";
|
|
@@ -21765,8 +22200,8 @@ async function defaultRunJob(job) {
|
|
|
21765
22200
|
const workdir = process.env.RUNNER_WORKDIR ?? DEFAULT_WORKDIR;
|
|
21766
22201
|
const branch = job.ref ?? "main";
|
|
21767
22202
|
const authUrl = `https://x-access-token:${job.githubToken}@github.com/${job.repo}.git`;
|
|
21768
|
-
|
|
21769
|
-
|
|
22203
|
+
fs50.rmSync(workdir, { recursive: true, force: true });
|
|
22204
|
+
fs50.mkdirSync(workdir, { recursive: true });
|
|
21770
22205
|
const allSecrets = typeof job.allSecrets === "string" ? job.allSecrets : JSON.stringify(job.allSecrets ?? {});
|
|
21771
22206
|
const interactive = job.mode === "interactive";
|
|
21772
22207
|
const scheduled = job.mode === "scheduled";
|