@kontextmind/kxm 0.7.96 → 0.7.97
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +22 -0
- package/docs/concepts/trust-model.md +3 -2
- package/docs/glossary.md +1 -1
- package/docs/guides/peer-messaging.md +2 -2
- package/docs/guides/pi-workers.md +1 -1
- package/docs/guides/webhook-workflows.md +53 -18
- package/docs/operations/deploy.md +1 -1
- package/docs/operations/troubleshooting.md +3 -2
- package/docs/reference/cli-reference.md +6 -6
- package/docs/reference/configuration.md +2 -2
- package/docs/reference/http-api.md +6 -6
- package/docs/reference/tools.md +1 -1
- package/docs/reference/workflow-definitions.md +2 -2
- package/docs/start/quickstart-pi.md +1 -1
- package/examples/workflow-signal.ts +4 -5
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/claude-hook.js +11 -1
- package/plugins/kxm/dist/cli.js +159 -74
- package/plugins/kxm/dist/client.js +3 -1
- package/plugins/kxm/dist/core.js +11 -1
- package/plugins/kxm/dist/extension.js +45 -13
- package/plugins/kxm/dist/mcp-server.js +20 -4
- package/plugins/kxm/dist/runtime-supervisor.js +1 -3
- package/plugins/kxm/dist/runtime.js +17 -3
- package/plugins/kxm/dist/server.js +115 -20
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/workflows.ts +12 -7
- package/plugins/kxm/src/cli.ts +19 -5
- package/plugins/kxm/src/client.ts +4 -0
- package/plugins/kxm/src/commands.ts +23 -1
- package/plugins/kxm/src/extension.ts +20 -14
- package/plugins/kxm/src/github-watch.ts +8 -5
- package/plugins/kxm/src/hub-env.ts +19 -1
- package/plugins/kxm/src/hub.ts +105 -21
- package/plugins/kxm/src/improve-sources.ts +2 -7
- package/plugins/kxm/src/mcp-server.ts +9 -2
- package/plugins/kxm/src/runtime-store.ts +23 -0
- package/plugins/kxm/src/workflow.ts +70 -1
- package/scripts/smoke-multi-pi.mjs +5 -1
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -18475,7 +18475,7 @@ function validateTerminalReceipt(value) {
|
|
|
18475
18475
|
}
|
|
18476
18476
|
|
|
18477
18477
|
// plugins/kxm/src/workflow.ts
|
|
18478
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
18478
|
+
import { createHash as createHash2, createHmac } from "node:crypto";
|
|
18479
18479
|
|
|
18480
18480
|
// plugins/kxm/src/redact.ts
|
|
18481
18481
|
var SECRET_PATTERNS = [
|
|
@@ -19123,6 +19123,37 @@ function parseOutcomeMap(stageId, raw) {
|
|
|
19123
19123
|
}
|
|
19124
19124
|
return map;
|
|
19125
19125
|
}
|
|
19126
|
+
var WORKFLOW_WEBHOOK_SIGNATURE_VERSION = "kxm-webhook-v1";
|
|
19127
|
+
function workflowWebhookSignedMaterial(scope, timestamp, deliveryId, body) {
|
|
19128
|
+
const fields = [
|
|
19129
|
+
WORKFLOW_WEBHOOK_SIGNATURE_VERSION,
|
|
19130
|
+
scope.runId === void 0 ? "start" : "signal",
|
|
19131
|
+
timestamp,
|
|
19132
|
+
deliveryId,
|
|
19133
|
+
scope.definitionId,
|
|
19134
|
+
scope.runId ?? "",
|
|
19135
|
+
scope.signalKey ?? ""
|
|
19136
|
+
];
|
|
19137
|
+
if (fields.some((field) => /[\r\n]/.test(field))) {
|
|
19138
|
+
throw new ProtocolError(400, "webhook signature fields must not contain line breaks", "webhook_signature_field_invalid");
|
|
19139
|
+
}
|
|
19140
|
+
return Buffer.concat([
|
|
19141
|
+
Buffer.from(`${fields.join("\n")}
|
|
19142
|
+
`, "utf8"),
|
|
19143
|
+
typeof body === "string" ? Buffer.from(body, "utf8") : Buffer.from(body)
|
|
19144
|
+
]);
|
|
19145
|
+
}
|
|
19146
|
+
function workflowWebhookSignature(secret, scope, timestamp, deliveryId, body) {
|
|
19147
|
+
return `sha256=${createHmac("sha256", secret).update(workflowWebhookSignedMaterial(scope, timestamp, deliveryId, body)).digest("hex")}`;
|
|
19148
|
+
}
|
|
19149
|
+
function workflowWebhookHeaders(input) {
|
|
19150
|
+
const timestamp = String(Math.floor((input.nowMs ?? Date.now()) / 1e3));
|
|
19151
|
+
return {
|
|
19152
|
+
"x-kxm-delivery-id": input.deliveryId,
|
|
19153
|
+
"x-kxm-timestamp": timestamp,
|
|
19154
|
+
"x-kxm-signature": workflowWebhookSignature(input.secret, input.scope, timestamp, input.deliveryId, input.body)
|
|
19155
|
+
};
|
|
19156
|
+
}
|
|
19126
19157
|
function resolveOutcomeRule(stage, outcomeKey) {
|
|
19127
19158
|
const raw = stage.on?.[outcomeKey];
|
|
19128
19159
|
return raw === void 0 ? void 0 : normalizeOutcomeValue(raw, `stage ${stage.id} on.${outcomeKey}`);
|
|
@@ -19552,7 +19583,9 @@ var HubClient = class {
|
|
|
19552
19583
|
options.workflowContext
|
|
19553
19584
|
)
|
|
19554
19585
|
} : {},
|
|
19555
|
-
...options.ttlMs ? { ttlMs: options.ttlMs } : {}
|
|
19586
|
+
...options.ttlMs ? { ttlMs: options.ttlMs } : {},
|
|
19587
|
+
...options.hops !== void 0 ? { hops: options.hops } : {},
|
|
19588
|
+
...options.maxHops !== void 0 ? { maxHops: options.maxHops } : {}
|
|
19556
19589
|
});
|
|
19557
19590
|
const completed2 = await this.awaitResponse(
|
|
19558
19591
|
message.id,
|
|
@@ -19946,6 +19979,24 @@ function resolveClientHubAuthToken(env, project) {
|
|
|
19946
19979
|
const record = readHubEnvRecord(env);
|
|
19947
19980
|
return record?.projectTokens?.[project]?.trim() || record?.authToken?.trim() || void 0;
|
|
19948
19981
|
}
|
|
19982
|
+
function resolveAgentHubAuthToken(env, project) {
|
|
19983
|
+
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
19984
|
+
if (envToken) return envToken;
|
|
19985
|
+
const tokens = readHubEnvRecord(env)?.projectTokens;
|
|
19986
|
+
if (!tokens || !Object.hasOwn(tokens, project)) return void 0;
|
|
19987
|
+
return tokens[project]?.trim() || void 0;
|
|
19988
|
+
}
|
|
19989
|
+
var AgentProjectTokenMissingError = class extends Error {
|
|
19990
|
+
code = "project_token_missing";
|
|
19991
|
+
project;
|
|
19992
|
+
constructor(project) {
|
|
19993
|
+
super(
|
|
19994
|
+
`kxm has no project token for project ${project} on this machine. Set KXM_AUTH_TOKEN to that project's token, or add ${project} to the hub KXM_PROJECT_TOKENS (list every existing project too, because that variable replaces the saved map). An agent never uses the hub admin token.`
|
|
19995
|
+
);
|
|
19996
|
+
this.name = "AgentProjectTokenMissingError";
|
|
19997
|
+
this.project = project;
|
|
19998
|
+
}
|
|
19999
|
+
};
|
|
19949
20000
|
function resolveClientAdminAuthToken(env = process.env) {
|
|
19950
20001
|
const envToken = env.KXM_AUTH_TOKEN?.trim();
|
|
19951
20002
|
if (envToken) return envToken;
|
|
@@ -19971,6 +20022,13 @@ import { createHash as createHash4, randomUUID as randomUUID2, timingSafeEqual }
|
|
|
19971
20022
|
import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
19972
20023
|
import { homedir as homedir2 } from "node:os";
|
|
19973
20024
|
import { dirname as dirname3, join as join5, resolve as resolve2 } from "node:path";
|
|
20025
|
+
function forwardedHops(handling) {
|
|
20026
|
+
if (!handling?.length) return void 0;
|
|
20027
|
+
return {
|
|
20028
|
+
hops: Math.max(...handling.map((message) => message.hops)) + 1,
|
|
20029
|
+
maxHops: Math.min(...handling.map((message) => message.maxHops))
|
|
20030
|
+
};
|
|
20031
|
+
}
|
|
19974
20032
|
function requiredString(value, name) {
|
|
19975
20033
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
19976
20034
|
return value.trim();
|
|
@@ -20100,12 +20158,13 @@ var AGENT_COMMANDS = [
|
|
|
20100
20158
|
required: ["target", "content"],
|
|
20101
20159
|
additionalProperties: false
|
|
20102
20160
|
},
|
|
20103
|
-
async execute(client, args) {
|
|
20161
|
+
async execute(client, args, context) {
|
|
20104
20162
|
const delivery = optionalString2(args.delivery);
|
|
20105
20163
|
const correlationId = optionalString2(args.correlationId);
|
|
20106
20164
|
const idempotencyKey = optionalString2(args.idempotencyKey);
|
|
20107
20165
|
const workflowContext = optionalWorkflowContext(args.workflowContext);
|
|
20108
20166
|
const message = await client.send({
|
|
20167
|
+
...forwardedHops(context?.handling),
|
|
20109
20168
|
target: requiredString(args.target, "target"),
|
|
20110
20169
|
content: requiredString(args.content, "content"),
|
|
20111
20170
|
...delivery ? { delivery } : {},
|
|
@@ -20183,6 +20242,7 @@ var AGENT_COMMANDS = [
|
|
|
20183
20242
|
const targets = Array.isArray(args.targets) ? args.targets.map((t) => requiredString(t, "target")) : [];
|
|
20184
20243
|
return {
|
|
20185
20244
|
responses: await client.fanout({
|
|
20245
|
+
...forwardedHops(context?.handling),
|
|
20186
20246
|
targets,
|
|
20187
20247
|
content: requiredString(args.content, "content"),
|
|
20188
20248
|
...optionalString2(args.correlationId) ? { correlationId: optionalString2(args.correlationId) } : {},
|
|
@@ -22985,8 +23045,8 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
22985
23045
|
const writable = Object.values(objectValue(step.repositories) ?? {}).filter((access) => access === "write").length;
|
|
22986
23046
|
if (maxWriteRepositories > writable) issues.push(issue2("semantic", "write_repository_bound_invalid", file, `${stepId} maxWriteRepositories exceeds writable repository scope`));
|
|
22987
23047
|
}
|
|
22988
|
-
const
|
|
22989
|
-
const minimumPassed =
|
|
23048
|
+
const join49 = objectValue(step.join);
|
|
23049
|
+
const minimumPassed = join49 && typeof join49.minimumPassed === "number" ? join49.minimumPassed : void 0;
|
|
22990
23050
|
if (minimumPassed !== void 0 && minimumPassed > maximum) issues.push(issue2("semantic", "join_impossible", file, `${stepId} minimumPassed exceeds assignment maximum`));
|
|
22991
23051
|
const distinctBy = names(assignment?.distinctBy);
|
|
22992
23052
|
if (distinctBy.length > 0) {
|
|
@@ -23530,7 +23590,7 @@ function planKxmInitialization(start = process.cwd(), options = {}) {
|
|
|
23530
23590
|
|
|
23531
23591
|
// plugins/kxm/src/runtime-supervisor.ts
|
|
23532
23592
|
import { spawn as spawn2 } from "node:child_process";
|
|
23533
|
-
import { createHash as createHash13, createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
23593
|
+
import { createHash as createHash13, createHmac as createHmac2, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
23534
23594
|
import { chmodSync as chmodSync4, existsSync as existsSync16, lstatSync as lstatSync6, mkdirSync as mkdirSync11, readFileSync as readFileSync14, renameSync as renameSync5, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "node:fs";
|
|
23535
23595
|
import { dirname as dirname11, isAbsolute as isAbsolute6, join as join15 } from "node:path";
|
|
23536
23596
|
|
|
@@ -23539,25 +23599,6 @@ import { createHash as createHash10, randomUUID as randomUUID4 } from "node:cryp
|
|
|
23539
23599
|
import { existsSync as existsSync10, lstatSync as lstatSync4, mkdirSync as mkdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
23540
23600
|
import { dirname as dirname7, join as join9, resolve as resolve7 } from "node:path";
|
|
23541
23601
|
|
|
23542
|
-
// plugins/kxm/src/bindings.ts
|
|
23543
|
-
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
23544
|
-
import { createHash as createHash7, randomUUID as randomUUID3 } from "node:crypto";
|
|
23545
|
-
import {
|
|
23546
|
-
chmodSync as chmodSync2,
|
|
23547
|
-
closeSync,
|
|
23548
|
-
existsSync as existsSync8,
|
|
23549
|
-
fsyncSync,
|
|
23550
|
-
lstatSync as lstatSync2,
|
|
23551
|
-
mkdirSync as mkdirSync4,
|
|
23552
|
-
openSync,
|
|
23553
|
-
readFileSync as readFileSync6,
|
|
23554
|
-
realpathSync as realpathSync2,
|
|
23555
|
-
renameSync as renameSync2,
|
|
23556
|
-
rmSync as rmSync2,
|
|
23557
|
-
writeFileSync as writeFileSync4
|
|
23558
|
-
} from "node:fs";
|
|
23559
|
-
import { homedir as homedir3 } from "node:os";
|
|
23560
|
-
|
|
23561
23602
|
// plugins/kxm/src/sqlite.ts
|
|
23562
23603
|
import { existsSync as existsSync7 } from "node:fs";
|
|
23563
23604
|
import { createRequire } from "node:module";
|
|
@@ -23607,6 +23648,23 @@ function openReadOnlyDatabase(path4) {
|
|
|
23607
23648
|
}
|
|
23608
23649
|
|
|
23609
23650
|
// plugins/kxm/src/bindings.ts
|
|
23651
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
23652
|
+
import { createHash as createHash7, randomUUID as randomUUID3 } from "node:crypto";
|
|
23653
|
+
import {
|
|
23654
|
+
chmodSync as chmodSync2,
|
|
23655
|
+
closeSync,
|
|
23656
|
+
existsSync as existsSync8,
|
|
23657
|
+
fsyncSync,
|
|
23658
|
+
lstatSync as lstatSync2,
|
|
23659
|
+
mkdirSync as mkdirSync4,
|
|
23660
|
+
openSync,
|
|
23661
|
+
readFileSync as readFileSync6,
|
|
23662
|
+
realpathSync as realpathSync2,
|
|
23663
|
+
renameSync as renameSync2,
|
|
23664
|
+
rmSync as rmSync2,
|
|
23665
|
+
writeFileSync as writeFileSync4
|
|
23666
|
+
} from "node:fs";
|
|
23667
|
+
import { homedir as homedir3 } from "node:os";
|
|
23610
23668
|
import { dirname as dirname5, isAbsolute as isAbsolute3, join as join7, parse, relative as relative2, resolve as resolve5, sep as sep2 } from "node:path";
|
|
23611
23669
|
var MAX_BINDING_RECORD_BYTES = 256 * 1024;
|
|
23612
23670
|
var BINDING_LABEL = "Runtime-local repository bindings";
|
|
@@ -24409,6 +24467,20 @@ function projectRuntimeKey(projectRoot) {
|
|
|
24409
24467
|
const folded = process.platform === "win32" ? canonical2.toLocaleLowerCase("en-US") : canonical2;
|
|
24410
24468
|
return createHash10("sha256").update(folded, "utf8").digest("hex").slice(0, 24);
|
|
24411
24469
|
}
|
|
24470
|
+
function kxmProjectRunEventsPath(projectRoot, env) {
|
|
24471
|
+
return join9(kxmRuntimePaths({ env }).projectsDir, projectRuntimeKey(projectRoot), "run-events.db");
|
|
24472
|
+
}
|
|
24473
|
+
function projectRuntimeOwnsRun(projectRoot, runId, env) {
|
|
24474
|
+
const path4 = kxmProjectRunEventsPath(projectRoot, env);
|
|
24475
|
+
if (!existsSync10(path4)) return false;
|
|
24476
|
+
const database = new DatabaseSync(path4, { readOnly: true });
|
|
24477
|
+
try {
|
|
24478
|
+
database.exec("PRAGMA busy_timeout = 5000");
|
|
24479
|
+
return database.prepare("SELECT 1 FROM runs WHERE run_id = ?").get(runId) !== void 0;
|
|
24480
|
+
} finally {
|
|
24481
|
+
database.close();
|
|
24482
|
+
}
|
|
24483
|
+
}
|
|
24412
24484
|
var KXM_REGISTRY_SCHEMA_VERSION = 1;
|
|
24413
24485
|
var REGISTRY_TABLES = {
|
|
24414
24486
|
supervisor: ["singleton_id", "runtime_id", "pid", "port", "token_hash", "started_at", "heartbeat_at", "state"],
|
|
@@ -24875,7 +24947,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
24875
24947
|
const maxAttempts = compileCountField(step.maxAttempts, 1, `${id}.maxAttempts`, id, sink);
|
|
24876
24948
|
const timeoutMs = compileOptionalDuration(step.timeoutMs, `${id}.timeoutMs`, id, sink);
|
|
24877
24949
|
const assignments = compileAssignments(step, id, agent, sink);
|
|
24878
|
-
const
|
|
24950
|
+
const join49 = compileJoin(step, id, sink);
|
|
24879
24951
|
const requiredEvidence = compileEvidence(step, id, sink);
|
|
24880
24952
|
const transitions = compileTransitions(step, id, index, stepIndex, sink);
|
|
24881
24953
|
const outcomes = Object.keys(transitions).sort(compareCodeUnits4);
|
|
@@ -24903,7 +24975,7 @@ function compileStep(step, index, stepIndex, requirePlanHash, sink) {
|
|
|
24903
24975
|
transitions: orderedTransitions,
|
|
24904
24976
|
requiresPlanHash: requirePlanHash.includes(id),
|
|
24905
24977
|
assignments,
|
|
24906
|
-
join:
|
|
24978
|
+
join: join49
|
|
24907
24979
|
};
|
|
24908
24980
|
if (kind === "agent" || kind === "moa") {
|
|
24909
24981
|
if (!agent) return void 0;
|
|
@@ -24953,15 +25025,15 @@ function compileAssignments(step, stepId, primaryAgentId, sink) {
|
|
|
24953
25025
|
};
|
|
24954
25026
|
}
|
|
24955
25027
|
function compileJoin(step, stepId, sink) {
|
|
24956
|
-
const
|
|
24957
|
-
if (!
|
|
24958
|
-
const declared = stringValue2(
|
|
25028
|
+
const join49 = objectValue2(step.join);
|
|
25029
|
+
if (!join49) return { strategy: "all" };
|
|
25030
|
+
const declared = stringValue2(join49.strategy);
|
|
24959
25031
|
const strategy = declared && JOIN_STRATEGIES.has(declared) ? declared : "all";
|
|
24960
|
-
const minimumPassed = compileOptionalCount(
|
|
25032
|
+
const minimumPassed = compileOptionalCount(join49.minimumPassed, `${stepId}.join.minimumPassed`, stepId, sink);
|
|
24961
25033
|
const compiled = {
|
|
24962
25034
|
strategy,
|
|
24963
25035
|
...minimumPassed !== void 0 ? { minimumPassed } : {},
|
|
24964
|
-
...typeof
|
|
25036
|
+
...typeof join49.cancelRemaining === "boolean" ? { cancelRemaining: join49.cancelRemaining } : {}
|
|
24965
25037
|
};
|
|
24966
25038
|
return compiled;
|
|
24967
25039
|
}
|
|
@@ -27026,7 +27098,7 @@ async function probeSupervisor(port, expectedRuntimeId, token, timeoutMs = 750)
|
|
|
27026
27098
|
}
|
|
27027
27099
|
}
|
|
27028
27100
|
function hashKxmTokenProof(token, nonce) {
|
|
27029
|
-
return
|
|
27101
|
+
return createHmac2("sha256", token).update(`kxm-runtime-token-proof\0${nonce}`, "utf8").digest("hex");
|
|
27030
27102
|
}
|
|
27031
27103
|
async function attachKxmSupervisor(options = {}) {
|
|
27032
27104
|
const paths = kxmRuntimePaths(options.stateRoot !== void 0 ? { stateRoot: options.stateRoot } : { ...options.env ? { env: options.env } : {} });
|
|
@@ -28639,7 +28711,7 @@ async function cmdRoleResume(runtime, runId, ruling) {
|
|
|
28639
28711
|
}
|
|
28640
28712
|
|
|
28641
28713
|
// plugins/kxm/src/cli/workflows.ts
|
|
28642
|
-
import {
|
|
28714
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
28643
28715
|
import { existsSync as existsSync21, readFileSync as readFileSync20 } from "node:fs";
|
|
28644
28716
|
import { join as join22, resolve as resolve17 } from "node:path";
|
|
28645
28717
|
|
|
@@ -28880,7 +28952,7 @@ function writeRetrospective(outDir, doc) {
|
|
|
28880
28952
|
}
|
|
28881
28953
|
|
|
28882
28954
|
// plugins/kxm/src/github-watch.ts
|
|
28883
|
-
import {
|
|
28955
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
28884
28956
|
async function fetchWithTimeout(fetchImpl, input, init, timeoutMs) {
|
|
28885
28957
|
const controller = new AbortController();
|
|
28886
28958
|
const timer = setTimeout(() => controller.abort(), Math.max(1, timeoutMs));
|
|
@@ -28928,7 +29000,6 @@ function mapCheckConclusion(runs, required = []) {
|
|
|
28928
29000
|
}
|
|
28929
29001
|
async function postWorkflowSignal(input) {
|
|
28930
29002
|
const body = JSON.stringify({ status: input.status, summary: input.summary, evidence: input.evidence });
|
|
28931
|
-
const signature = `sha256=${createHmac2("sha256", input.signalSecret).update(body).digest("hex")}`;
|
|
28932
29003
|
const endpoint = [
|
|
28933
29004
|
input.serverUrl.replace(/\/$/, ""),
|
|
28934
29005
|
"v1/webhooks",
|
|
@@ -28942,8 +29013,12 @@ async function postWorkflowSignal(input) {
|
|
|
28942
29013
|
method: "POST",
|
|
28943
29014
|
headers: {
|
|
28944
29015
|
"content-type": "application/json",
|
|
28945
|
-
|
|
28946
|
-
|
|
29016
|
+
...workflowWebhookHeaders({
|
|
29017
|
+
secret: input.signalSecret,
|
|
29018
|
+
scope: { definitionId: input.definitionId, runId: input.runId, signalKey: input.signalKey },
|
|
29019
|
+
deliveryId: input.deliveryId,
|
|
29020
|
+
body
|
|
29021
|
+
})
|
|
28947
29022
|
},
|
|
28948
29023
|
body
|
|
28949
29024
|
}, input.timeoutMs ?? 15e3);
|
|
@@ -29373,13 +29448,16 @@ function localWorkflowSnapshot(dataPath, runId) {
|
|
|
29373
29448
|
async function postWorkflowStart(input) {
|
|
29374
29449
|
const payload = input.event && input.payload["event"] === void 0 ? { ...input.payload, event: input.event } : input.payload;
|
|
29375
29450
|
const body = JSON.stringify(payload);
|
|
29376
|
-
const signature = `sha256=${createHmac3("sha256", input.secret).update(body).digest("hex")}`;
|
|
29377
29451
|
const response = await input.fetchImpl(`${input.serverUrl.replace(/\/$/, "")}/v1/webhooks/${encodeURIComponent(input.definitionId)}`, {
|
|
29378
29452
|
method: "POST",
|
|
29379
29453
|
headers: {
|
|
29380
29454
|
"content-type": "application/json",
|
|
29381
|
-
|
|
29382
|
-
|
|
29455
|
+
...workflowWebhookHeaders({
|
|
29456
|
+
secret: input.secret,
|
|
29457
|
+
scope: { definitionId: input.definitionId },
|
|
29458
|
+
deliveryId: input.deliveryId,
|
|
29459
|
+
body
|
|
29460
|
+
}),
|
|
29383
29461
|
...input.event ? { "x-github-event": input.event } : {}
|
|
29384
29462
|
},
|
|
29385
29463
|
body
|
|
@@ -29393,7 +29471,7 @@ async function postWorkflowStart(input) {
|
|
|
29393
29471
|
if (!response.ok) throw new Error(`workflow_start_http_${response.status}`);
|
|
29394
29472
|
return {
|
|
29395
29473
|
status: response.status,
|
|
29396
|
-
...parsed.
|
|
29474
|
+
...parsed.runId ? { runId: parsed.runId } : {},
|
|
29397
29475
|
duplicate: parsed.duplicate === true
|
|
29398
29476
|
};
|
|
29399
29477
|
}
|
|
@@ -29798,7 +29876,7 @@ async function cmdSignal(runtime, runId, signalKey, status, summary, evidenceArg
|
|
|
29798
29876
|
}
|
|
29799
29877
|
const worker = gateOf(runtime, "signal");
|
|
29800
29878
|
const projectRoot = discoverKxmProjectRoot(runtime.cwd);
|
|
29801
|
-
if (projectRoot &&
|
|
29879
|
+
if (projectRoot && projectRuntimeOwnsRun(projectRoot, runId, runtime.env)) {
|
|
29802
29880
|
if (runtime.dryRun) {
|
|
29803
29881
|
printWorker(runtime, worker, { ok: true, command: "signal", dryRun: true, runId, signalKey, status, summary, evidence }, "would post signal to KXM run");
|
|
29804
29882
|
return 0;
|
|
@@ -45756,7 +45834,7 @@ import { spawnSync as spawnSync8 } from "node:child_process";
|
|
|
45756
45834
|
import { createHash as createHash16 } from "node:crypto";
|
|
45757
45835
|
import { existsSync as existsSync40, mkdtempSync as mkdtempSync3, readFileSync as readFileSync37, rmSync as rmSync13 } from "node:fs";
|
|
45758
45836
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
45759
|
-
import { join as
|
|
45837
|
+
import { join as join47, resolve as resolve31 } from "node:path";
|
|
45760
45838
|
import { createInterface as createInterface3 } from "node:readline";
|
|
45761
45839
|
|
|
45762
45840
|
// plugins/kxm/src/improve.ts
|
|
@@ -46167,12 +46245,9 @@ function evaluatePromotionPolicy(candidate, policy = "manual_pr", options = {})
|
|
|
46167
46245
|
|
|
46168
46246
|
// plugins/kxm/src/improve-sources.ts
|
|
46169
46247
|
import { existsSync as existsSync35 } from "node:fs";
|
|
46170
|
-
import {
|
|
46248
|
+
import { resolve as resolve28 } from "node:path";
|
|
46171
46249
|
var ENGINE_EVENTS_SQL = "SELECT run_id, sequence, event_type, payload FROM events WHERE event_type IN ('routing.attempt.recorded','step.entered','run.status_changed') ORDER BY run_id, sequence";
|
|
46172
46250
|
var SIMULATED_HARNESS = "driver-simulated";
|
|
46173
|
-
function kxmProjectRunEventsPath(projectRoot, env) {
|
|
46174
|
-
return join43(kxmRuntimePaths({ env }).projectsDir, projectRuntimeKey(projectRoot), "run-events.db");
|
|
46175
|
-
}
|
|
46176
46251
|
function parsePayload(text) {
|
|
46177
46252
|
try {
|
|
46178
46253
|
const value = JSON.parse(text);
|
|
@@ -46313,7 +46388,7 @@ function loadRoutingSources(options) {
|
|
|
46313
46388
|
// plugins/kxm/src/modes.ts
|
|
46314
46389
|
var import_yaml16 = __toESM(require_dist(), 1);
|
|
46315
46390
|
import { existsSync as existsSync36, readFileSync as readFileSync34 } from "node:fs";
|
|
46316
|
-
import { join as
|
|
46391
|
+
import { join as join43 } from "node:path";
|
|
46317
46392
|
var DEFAULT_MODES_CONFIG = Object.freeze({
|
|
46318
46393
|
schema: "kxm.modes.v1",
|
|
46319
46394
|
majorModes: {
|
|
@@ -46376,7 +46451,7 @@ function loadModesConfig(projectRoot) {
|
|
|
46376
46451
|
if (!projectRoot) {
|
|
46377
46452
|
return DEFAULT_MODES_CONFIG;
|
|
46378
46453
|
}
|
|
46379
|
-
const modesPath =
|
|
46454
|
+
const modesPath = join43(projectRoot, ".kxm", "modes.yaml");
|
|
46380
46455
|
if (!existsSync36(modesPath)) {
|
|
46381
46456
|
return DEFAULT_MODES_CONFIG;
|
|
46382
46457
|
}
|
|
@@ -46467,7 +46542,7 @@ function calculatePromptFootprint(resolved, projectRoot = process.cwd(), catalog
|
|
|
46467
46542
|
estimatedTokens: estimateTokens(baseSystemPromptChars)
|
|
46468
46543
|
});
|
|
46469
46544
|
for (const relPath of resolved.contextFiles) {
|
|
46470
|
-
const fullPath =
|
|
46545
|
+
const fullPath = join43(projectRoot, relPath);
|
|
46471
46546
|
let chars = 0;
|
|
46472
46547
|
if (existsSync36(fullPath)) {
|
|
46473
46548
|
try {
|
|
@@ -46605,7 +46680,7 @@ ${divider}
|
|
|
46605
46680
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
46606
46681
|
import { existsSync as existsSync37, mkdirSync as mkdirSync28, readFileSync as readFileSync35, readdirSync as readdirSync13, rmSync as rmSync12, statSync as statSync5 } from "node:fs";
|
|
46607
46682
|
import { homedir as homedir8 } from "node:os";
|
|
46608
|
-
import { join as
|
|
46683
|
+
import { join as join44, resolve as resolve29 } from "node:path";
|
|
46609
46684
|
var MAX_SSH_OUTPUT_BYTES = 50 * 1024;
|
|
46610
46685
|
var MAX_SSH_OUTPUT_LINES = 2e3;
|
|
46611
46686
|
var DEFAULT_SOCKET_DIR = ".kxm/run/ssh-sockets";
|
|
@@ -46631,7 +46706,7 @@ function truncateSshOutput(raw) {
|
|
|
46631
46706
|
return { text, truncated };
|
|
46632
46707
|
}
|
|
46633
46708
|
function parseSshConfig(configPath) {
|
|
46634
|
-
const targetPath = configPath ??
|
|
46709
|
+
const targetPath = configPath ?? join44(homedir8(), ".ssh", "config");
|
|
46635
46710
|
if (!existsSync37(targetPath)) {
|
|
46636
46711
|
return [];
|
|
46637
46712
|
}
|
|
@@ -46721,7 +46796,7 @@ function ensureSocketDir(socketDir = DEFAULT_SOCKET_DIR) {
|
|
|
46721
46796
|
}
|
|
46722
46797
|
function buildSshArgs(options) {
|
|
46723
46798
|
const socketDir = ensureSocketDir(options.socketDir ?? DEFAULT_SOCKET_DIR);
|
|
46724
|
-
const controlPath =
|
|
46799
|
+
const controlPath = join44(socketDir, "%C");
|
|
46725
46800
|
const persist = options.controlPersist ?? DEFAULT_CONTROL_PERSIST;
|
|
46726
46801
|
const args = [
|
|
46727
46802
|
"-o",
|
|
@@ -46746,7 +46821,7 @@ function buildSshArgs(options) {
|
|
|
46746
46821
|
}
|
|
46747
46822
|
function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
|
|
46748
46823
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
46749
|
-
const controlPath =
|
|
46824
|
+
const controlPath = join44(resolvedDir, "%C");
|
|
46750
46825
|
try {
|
|
46751
46826
|
const result = execFn("ssh", ["-O", "check", "-o", `ControlPath=${controlPath}`, host], {
|
|
46752
46827
|
encoding: "utf-8"
|
|
@@ -46758,7 +46833,7 @@ function checkControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawn
|
|
|
46758
46833
|
}
|
|
46759
46834
|
function closeControlSocket(host, socketDir = DEFAULT_SOCKET_DIR, execFn = spawnSync7) {
|
|
46760
46835
|
const resolvedDir = ensureSocketDir(socketDir);
|
|
46761
|
-
const controlPath =
|
|
46836
|
+
const controlPath = join44(resolvedDir, "%C");
|
|
46762
46837
|
try {
|
|
46763
46838
|
const result = execFn("ssh", ["-O", "stop", "-o", `ControlPath=${controlPath}`, host], {
|
|
46764
46839
|
encoding: "utf-8"
|
|
@@ -47205,7 +47280,7 @@ complete -c kxm -n "__fish_seen_subcommand_from goal" -a "create list get"
|
|
|
47205
47280
|
// plugins/kxm/src/completion-install.ts
|
|
47206
47281
|
import { existsSync as existsSync38, mkdirSync as mkdirSync29, readFileSync as readFileSync36, writeFileSync as writeFileSync25 } from "node:fs";
|
|
47207
47282
|
import { homedir as homedir9 } from "node:os";
|
|
47208
|
-
import { basename as basename9, delimiter, dirname as dirname23, isAbsolute as isAbsolute9, join as
|
|
47283
|
+
import { basename as basename9, delimiter, dirname as dirname23, isAbsolute as isAbsolute9, join as join45, resolve as resolve30 } from "node:path";
|
|
47209
47284
|
var COMPLETION_MARKER = "# kxm completion";
|
|
47210
47285
|
var PATH_MARKER = "# kxm path";
|
|
47211
47286
|
function detectShell(env = process.env, platform = process.platform) {
|
|
@@ -47227,25 +47302,25 @@ function completionScriptPath(shell, options = {}) {
|
|
|
47227
47302
|
const env = options.env ?? process.env;
|
|
47228
47303
|
const explicit = options.configDir ?? env.KXM_USER_CONFIG_DIR?.trim();
|
|
47229
47304
|
const base = explicit && explicit.length > 0 ? resolve30(explicit) : resolve30(effectiveHome(options), ".config", "kxm");
|
|
47230
|
-
return
|
|
47305
|
+
return join45(base, "completions", `kxm.${shell}`);
|
|
47231
47306
|
}
|
|
47232
47307
|
function bashRcCandidate(options) {
|
|
47233
47308
|
const home = effectiveHome(options);
|
|
47234
|
-
const candidates = [
|
|
47309
|
+
const candidates = [join45(home, ".bashrc"), join45(home, ".bash_profile")];
|
|
47235
47310
|
const existing = candidates.find((candidate) => existsSync38(candidate));
|
|
47236
47311
|
return existing ?? candidates[0];
|
|
47237
47312
|
}
|
|
47238
47313
|
function zshRcCandidate(options) {
|
|
47239
47314
|
const env = options.env ?? process.env;
|
|
47240
47315
|
const home = effectiveHome(options);
|
|
47241
|
-
if (env.ZDOTDIR?.trim()) return
|
|
47242
|
-
return
|
|
47316
|
+
if (env.ZDOTDIR?.trim()) return join45(resolve30(env.ZDOTDIR.trim()), ".zshrc");
|
|
47317
|
+
return join45(home, ".zshrc");
|
|
47243
47318
|
}
|
|
47244
47319
|
function fishCompletionTarget(shell, options) {
|
|
47245
47320
|
const env = options.env ?? process.env;
|
|
47246
47321
|
const home = effectiveHome(options);
|
|
47247
|
-
if (env.XDG_CONFIG_HOME?.trim()) return
|
|
47248
|
-
return
|
|
47322
|
+
if (env.XDG_CONFIG_HOME?.trim()) return join45(resolve30(env.XDG_CONFIG_HOME.trim()), "fish", "completions", "kxm.fish");
|
|
47323
|
+
return join45(home, ".config", "fish", "completions", "kxm.fish");
|
|
47249
47324
|
}
|
|
47250
47325
|
function completionRcTarget(shell, options = {}) {
|
|
47251
47326
|
if (shell === "fish") {
|
|
@@ -47333,7 +47408,7 @@ function kxmBinDir(env = process.env) {
|
|
|
47333
47408
|
const argv1 = env.KXM_ENTRY ?? process.argv[1];
|
|
47334
47409
|
if (argv1 && isAbsolute9(argv1)) {
|
|
47335
47410
|
const dir = dirname23(argv1);
|
|
47336
|
-
if (existsSync38(
|
|
47411
|
+
if (existsSync38(join45(dir, process.platform === "win32" ? "kxm.cmd" : "kxm"))) return dir;
|
|
47337
47412
|
}
|
|
47338
47413
|
const pathEnv = env.PATH ?? "";
|
|
47339
47414
|
for (const part of pathEnv.split(delimiter)) {
|
|
@@ -47372,7 +47447,7 @@ ${line}
|
|
|
47372
47447
|
// plugins/kxm/src/init-guide-setup.ts
|
|
47373
47448
|
var import_yaml17 = __toESM(require_dist(), 1);
|
|
47374
47449
|
import { existsSync as existsSync39, mkdirSync as mkdirSync30, writeFileSync as writeFileSync26 } from "node:fs";
|
|
47375
|
-
import { dirname as dirname24, join as
|
|
47450
|
+
import { dirname as dirname24, join as join46 } from "node:path";
|
|
47376
47451
|
var NATIVE_VENDOR_HARNESS = Object.freeze({
|
|
47377
47452
|
anthropic: "claude",
|
|
47378
47453
|
openai: "codex",
|
|
@@ -47771,13 +47846,13 @@ function renderGuideSetupFiles(projectRoot, plan) {
|
|
|
47771
47846
|
const stage = roleStages.get(role);
|
|
47772
47847
|
if (!stage) continue;
|
|
47773
47848
|
files.push({
|
|
47774
|
-
path:
|
|
47849
|
+
path: join46(projectRoot, ".kxm", "agents", `${role}.yaml`),
|
|
47775
47850
|
content: (0, import_yaml17.stringify)(agentDocument(role, stage, binding))
|
|
47776
47851
|
});
|
|
47777
47852
|
}
|
|
47778
47853
|
for (const workflow of plan.workflows) {
|
|
47779
47854
|
files.push({
|
|
47780
|
-
path:
|
|
47855
|
+
path: join46(projectRoot, ".kxm", "workflows", `${workflow.slug}.yaml`),
|
|
47781
47856
|
content: (0, import_yaml17.stringify)(workflowDocument(workflow))
|
|
47782
47857
|
});
|
|
47783
47858
|
}
|
|
@@ -47855,7 +47930,7 @@ function applyKxmPackageUpdate(runtime, notice) {
|
|
|
47855
47930
|
detail: `release v${notice.latest} has no sha256 digest for ${name}; refusing to install`
|
|
47856
47931
|
};
|
|
47857
47932
|
}
|
|
47858
|
-
const releaseDir = mkdtempSync3(
|
|
47933
|
+
const releaseDir = mkdtempSync3(join47(tmpdir2(), "kxm-pkg-update-"));
|
|
47859
47934
|
try {
|
|
47860
47935
|
const planned = planKxmPackageUpdate(notice.source, notice.latest, releaseDir, notice.asset);
|
|
47861
47936
|
if (runtime.dryRun) {
|
|
@@ -48228,7 +48303,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
48228
48303
|
print(runtime.io, runtime.json, { ok: false, command: "improve", error: "config_invalid", detail: message }, `config_invalid: ${message}`);
|
|
48229
48304
|
return 1;
|
|
48230
48305
|
}
|
|
48231
|
-
const candidatesDir = options.outDir ? resolve31(runtime.cwd, options.outDir) :
|
|
48306
|
+
const candidatesDir = options.outDir ? resolve31(runtime.cwd, options.outDir) : join47(root, ".kxm", "candidates");
|
|
48232
48307
|
const report2 = buildImprovementReport(loaded.records, {
|
|
48233
48308
|
candidatesDir,
|
|
48234
48309
|
projectRoot: root,
|
|
@@ -48237,7 +48312,7 @@ async function cmdImprove(runtime, options = {}) {
|
|
|
48237
48312
|
autoThreshold: config.improvement.autoThreshold,
|
|
48238
48313
|
halfLifeDays: config.improvement.telemetryHalfLifeDays
|
|
48239
48314
|
});
|
|
48240
|
-
const reportDir =
|
|
48315
|
+
const reportDir = join47(runtime.dirs.assets, "improvements");
|
|
48241
48316
|
const reportPath = writeImprovementReport(reportDir, report2, runtime.dryRun);
|
|
48242
48317
|
const text = [
|
|
48243
48318
|
"Sources:",
|
|
@@ -48526,7 +48601,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
48526
48601
|
let catalog;
|
|
48527
48602
|
if (includeEquivalentListCost) {
|
|
48528
48603
|
try {
|
|
48529
|
-
const pricesPath = options.prices ? resolve31(runtime.cwd, options.prices) :
|
|
48604
|
+
const pricesPath = options.prices ? resolve31(runtime.cwd, options.prices) : join47(runtime.dirs.workspace, "prices.yaml");
|
|
48530
48605
|
catalog = loadPriceCatalog(pricesPath);
|
|
48531
48606
|
} catch {
|
|
48532
48607
|
}
|
|
@@ -48754,14 +48829,15 @@ async function ensureCliClient(runtime) {
|
|
|
48754
48829
|
const project = defaultProjectName(runtime.cwd, runtime.env);
|
|
48755
48830
|
const name = runtime.env.KXM_AGENT_NAME?.trim() || `cli-${process.pid}`;
|
|
48756
48831
|
const purpose = runtime.env.KXM_AGENT_PURPOSE?.trim() || "CLI agent client";
|
|
48757
|
-
const authToken =
|
|
48832
|
+
const authToken = resolveAgentHubAuthToken(runtime.env, project);
|
|
48833
|
+
if (!authToken) throw new AgentProjectTokenMissingError(project);
|
|
48758
48834
|
const client = new HubClient({
|
|
48759
48835
|
serverUrl,
|
|
48760
48836
|
name,
|
|
48761
48837
|
project,
|
|
48762
48838
|
purpose,
|
|
48763
48839
|
fetchImpl: runtime.fetchImpl,
|
|
48764
|
-
|
|
48840
|
+
authToken
|
|
48765
48841
|
});
|
|
48766
48842
|
await client.start(() => {
|
|
48767
48843
|
});
|
|
@@ -48822,7 +48898,7 @@ async function dispatchAgentCliCommand(runtime, toolName, rawArgs) {
|
|
|
48822
48898
|
if (toolName === "kxm_workflow_wait") {
|
|
48823
48899
|
const runId = typeof args.runId === "string" ? args.runId : void 0;
|
|
48824
48900
|
const projectRoot = discoverKxmProjectRoot(runtime.cwd);
|
|
48825
|
-
if (runId && projectRoot &&
|
|
48901
|
+
if (runId && projectRoot && projectRuntimeOwnsRun(projectRoot, runId, runtime.env)) {
|
|
48826
48902
|
if (runtime.dryRun) {
|
|
48827
48903
|
print(runtime.io, runtime.json, { ok: true, command: "workflow wait", runId, dryRun: true }, `would wait for signal on KXM run ${runId}`);
|
|
48828
48904
|
return 0;
|
|
@@ -48857,6 +48933,15 @@ async function dispatchAgentCliCommand(runtime, toolName, rawArgs) {
|
|
|
48857
48933
|
return 0;
|
|
48858
48934
|
} catch (error) {
|
|
48859
48935
|
const message = error instanceof Error ? error.message : String(error);
|
|
48936
|
+
if (error instanceof AgentProjectTokenMissingError) {
|
|
48937
|
+
print(
|
|
48938
|
+
runtime.io,
|
|
48939
|
+
runtime.json,
|
|
48940
|
+
{ ok: false, error: error.code, project: error.project, nextAction: "export_kxm_auth_token", detail: message },
|
|
48941
|
+
message
|
|
48942
|
+
);
|
|
48943
|
+
return 2;
|
|
48944
|
+
}
|
|
48860
48945
|
print(runtime.io, runtime.json, { ok: false, error: "command_failed", detail: message }, `command failed: ${message}`);
|
|
48861
48946
|
return 1;
|
|
48862
48947
|
} finally {
|
|
@@ -219,7 +219,9 @@ var HubClient = class {
|
|
|
219
219
|
options.workflowContext
|
|
220
220
|
)
|
|
221
221
|
} : {},
|
|
222
|
-
...options.ttlMs ? { ttlMs: options.ttlMs } : {}
|
|
222
|
+
...options.ttlMs ? { ttlMs: options.ttlMs } : {},
|
|
223
|
+
...options.hops !== void 0 ? { hops: options.hops } : {},
|
|
224
|
+
...options.maxHops !== void 0 ? { maxHops: options.maxHops } : {}
|
|
223
225
|
});
|
|
224
226
|
const completed = await this.awaitResponse(
|
|
225
227
|
message.id,
|
package/plugins/kxm/dist/core.js
CHANGED
|
@@ -981,6 +981,13 @@ var HubHttpError = class extends Error {
|
|
|
981
981
|
};
|
|
982
982
|
|
|
983
983
|
// plugins/kxm/src/commands.ts
|
|
984
|
+
function forwardedHops(handling) {
|
|
985
|
+
if (!handling?.length) return void 0;
|
|
986
|
+
return {
|
|
987
|
+
hops: Math.max(...handling.map((message) => message.hops)) + 1,
|
|
988
|
+
maxHops: Math.min(...handling.map((message) => message.maxHops))
|
|
989
|
+
};
|
|
990
|
+
}
|
|
984
991
|
function requiredString(value, name) {
|
|
985
992
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`${name} is required`);
|
|
986
993
|
return value.trim();
|
|
@@ -1110,12 +1117,13 @@ var AGENT_COMMANDS = [
|
|
|
1110
1117
|
required: ["target", "content"],
|
|
1111
1118
|
additionalProperties: false
|
|
1112
1119
|
},
|
|
1113
|
-
async execute(client, args) {
|
|
1120
|
+
async execute(client, args, context) {
|
|
1114
1121
|
const delivery = optionalString2(args.delivery);
|
|
1115
1122
|
const correlationId = optionalString2(args.correlationId);
|
|
1116
1123
|
const idempotencyKey = optionalString2(args.idempotencyKey);
|
|
1117
1124
|
const workflowContext = optionalWorkflowContext(args.workflowContext);
|
|
1118
1125
|
const message = await client.send({
|
|
1126
|
+
...forwardedHops(context?.handling),
|
|
1119
1127
|
target: requiredString(args.target, "target"),
|
|
1120
1128
|
content: requiredString(args.content, "content"),
|
|
1121
1129
|
...delivery ? { delivery } : {},
|
|
@@ -1193,6 +1201,7 @@ var AGENT_COMMANDS = [
|
|
|
1193
1201
|
const targets = Array.isArray(args.targets) ? args.targets.map((t) => requiredString(t, "target")) : [];
|
|
1194
1202
|
return {
|
|
1195
1203
|
responses: await client.fanout({
|
|
1204
|
+
...forwardedHops(context?.handling),
|
|
1196
1205
|
targets,
|
|
1197
1206
|
content: requiredString(args.content, "content"),
|
|
1198
1207
|
...optionalString2(args.correlationId) ? { correlationId: optionalString2(args.correlationId) } : {},
|
|
@@ -2156,6 +2165,7 @@ export {
|
|
|
2156
2165
|
enforceToolPolicy,
|
|
2157
2166
|
evaluateCircuitBreaker,
|
|
2158
2167
|
formatRoutingReport,
|
|
2168
|
+
forwardedHops,
|
|
2159
2169
|
gateWorker,
|
|
2160
2170
|
generateRoutingReport,
|
|
2161
2171
|
getCliAgentCommands,
|