@kenhkl/agent-moss 0.17.6 → 0.17.7
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/cli.js +55 -24
- package/dist/engine/coordinator.js +18 -10
- package/dist/server.js +55 -24
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1340,6 +1340,12 @@ function agentInflight() {
|
|
|
1340
1340
|
function boundAgentOf(principal) {
|
|
1341
1341
|
return principal.startsWith("agent:") ? principal.slice("agent:".length) : "";
|
|
1342
1342
|
}
|
|
1343
|
+
function chainScope() {
|
|
1344
|
+
return (env("AGENT_MOSS_CHAIN_SCOPE", "system") || "system").toLowerCase();
|
|
1345
|
+
}
|
|
1346
|
+
function chainBucket(agentId = "") {
|
|
1347
|
+
return chainScope() === "agent" ? agentId || "default" : "__system__";
|
|
1348
|
+
}
|
|
1343
1349
|
function rateLimitQps() {
|
|
1344
1350
|
return envInt("AGENT_MOSS_RATE_LIMIT_QPS", 100);
|
|
1345
1351
|
}
|
|
@@ -1411,6 +1417,8 @@ var init_models = __esm({
|
|
|
1411
1417
|
action_history: z.array(ActionItemSchema).default([]).describe("Historical action sequence"),
|
|
1412
1418
|
session_history: z.array(z.object({
|
|
1413
1419
|
session_id: z.string(),
|
|
1420
|
+
/** 来源 agent(AgentGate 逐会话带上):记录在链路径里供告警/取证,不参与链匹配。 */
|
|
1421
|
+
agent_id: z.string().optional(),
|
|
1414
1422
|
action_history: z.array(ActionItemSchema).default([])
|
|
1415
1423
|
})).default([]).describe("Multi-session historical actions (optional): for L2.2 formal engine cross-session combo-chain / sensitive-data-flow verification. Provided by caller (incl. future agentgate)."),
|
|
1416
1424
|
a_next: ActionItemSchema.describe("Next action to be executed"),
|
|
@@ -2999,7 +3007,7 @@ function _scenarioRulesToDefaults() {
|
|
|
2999
3007
|
if (!existsSync7(scenDir)) return out;
|
|
3000
3008
|
let entries;
|
|
3001
3009
|
try {
|
|
3002
|
-
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
3010
|
+
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("__")).map((d) => d.name);
|
|
3003
3011
|
} catch {
|
|
3004
3012
|
return out;
|
|
3005
3013
|
}
|
|
@@ -9379,7 +9387,7 @@ function markIntegrity(actionDetail) {
|
|
|
9379
9387
|
}
|
|
9380
9388
|
return { integrity: "medium", isLowSource: false };
|
|
9381
9389
|
}
|
|
9382
|
-
function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
9390
|
+
function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "") {
|
|
9383
9391
|
const { integrity, isLowSource } = markIntegrity(actionDetail);
|
|
9384
9392
|
return {
|
|
9385
9393
|
sessionId,
|
|
@@ -9387,13 +9395,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
|
9387
9395
|
actionType,
|
|
9388
9396
|
actionDetail,
|
|
9389
9397
|
stage: markStage(actionDetail),
|
|
9398
|
+
agentId: agentId || void 0,
|
|
9390
9399
|
resources: extractResources(actionDetail),
|
|
9391
9400
|
integrity,
|
|
9392
9401
|
isLowSource,
|
|
9393
9402
|
timestamp: timestamp || void 0
|
|
9394
9403
|
};
|
|
9395
9404
|
}
|
|
9396
|
-
function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
9405
|
+
function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
|
|
9397
9406
|
const nodes = [];
|
|
9398
9407
|
const edges = [];
|
|
9399
9408
|
const stageFlags = /* @__PURE__ */ new Set();
|
|
@@ -9403,18 +9412,20 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
|
9403
9412
|
if (ad) details.push({
|
|
9404
9413
|
actionType: String(a.actionType || ""),
|
|
9405
9414
|
actionDetail: ad,
|
|
9406
|
-
calledAt: a.calledAt || void 0
|
|
9415
|
+
calledAt: a.calledAt || void 0,
|
|
9416
|
+
agentId: a.agentId || agentId || void 0
|
|
9407
9417
|
});
|
|
9408
9418
|
}
|
|
9409
9419
|
if (aNext) {
|
|
9410
9420
|
details.push({
|
|
9411
9421
|
actionType: String(aNext.actionType || ""),
|
|
9412
9422
|
actionDetail: String(aNext.actionDetail || ""),
|
|
9413
|
-
calledAt: aNext.calledAt || void 0
|
|
9423
|
+
calledAt: aNext.calledAt || void 0,
|
|
9424
|
+
agentId: aNext.agentId || agentId || void 0
|
|
9414
9425
|
});
|
|
9415
9426
|
}
|
|
9416
9427
|
details.forEach((d, seq) => {
|
|
9417
|
-
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt);
|
|
9428
|
+
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
|
|
9418
9429
|
nodes.push(node);
|
|
9419
9430
|
if (node.stage) stageFlags.add(node.stage);
|
|
9420
9431
|
});
|
|
@@ -9431,7 +9442,7 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
9431
9442
|
}
|
|
9432
9443
|
for (const s of sessions) {
|
|
9433
9444
|
const sid = String(s.sessionId || "s");
|
|
9434
|
-
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid));
|
|
9445
|
+
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
|
|
9435
9446
|
}
|
|
9436
9447
|
if (aNext) {
|
|
9437
9448
|
const last = mg.sessions[mg.sessions.length - 1];
|
|
@@ -9441,7 +9452,8 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
9441
9452
|
last.nodes.length,
|
|
9442
9453
|
String(aNext.actionType || ""),
|
|
9443
9454
|
String(aNext.actionDetail || ""),
|
|
9444
|
-
aNext.calledAt || void 0
|
|
9455
|
+
aNext.calledAt || void 0,
|
|
9456
|
+
aNext.agentId || ""
|
|
9445
9457
|
));
|
|
9446
9458
|
if (last.nodes.length > 1) {
|
|
9447
9459
|
last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
|
|
@@ -10228,8 +10240,8 @@ var init_stateful = __esm({
|
|
|
10228
10240
|
}
|
|
10229
10241
|
/** 增量推进:把当前动作追加到时间线 → 链指针推进 → 判定。 */
|
|
10230
10242
|
advance(args) {
|
|
10231
|
-
const { aNext, sessionId = "current", isError = false } = args;
|
|
10232
|
-
const node = this.appendNode(aNext, sessionId, isError);
|
|
10243
|
+
const { aNext, sessionId = "current", isError = false, agentId = "" } = args;
|
|
10244
|
+
const node = this.appendNode(aNext, sessionId, isError, agentId);
|
|
10233
10245
|
if (!node) {
|
|
10234
10246
|
return { seq: this.seqNext, node: null, matched: null, pendingPrefixes: this.pendingPrefixes, exfil: [], shouldBlock: false };
|
|
10235
10247
|
}
|
|
@@ -10249,7 +10261,7 @@ var init_stateful = __esm({
|
|
|
10249
10261
|
}
|
|
10250
10262
|
};
|
|
10251
10263
|
}
|
|
10252
|
-
appendNode(action, sessionId, isError = false) {
|
|
10264
|
+
appendNode(action, sessionId, isError = false, agentId = "") {
|
|
10253
10265
|
const ad = String(action.actionDetail || "");
|
|
10254
10266
|
const at = String(action.actionType || "");
|
|
10255
10267
|
if (!ad) return null;
|
|
@@ -10266,6 +10278,7 @@ var init_stateful = __esm({
|
|
|
10266
10278
|
resources: extractResources2(ad),
|
|
10267
10279
|
instances: extractInstances(ad, stage),
|
|
10268
10280
|
isError,
|
|
10281
|
+
agentId: String(action.agentId || agentId || ""),
|
|
10269
10282
|
lifecycle: lifecycleFor(ad, stage, isError),
|
|
10270
10283
|
timestamp: typeof action.calledAt === "string" ? action.calledAt : _StatefulChainTracker.now()
|
|
10271
10284
|
};
|
|
@@ -10403,7 +10416,13 @@ var init_stateful = __esm({
|
|
|
10403
10416
|
let want = stages[0];
|
|
10404
10417
|
for (const n of this.nodes_) {
|
|
10405
10418
|
if (n.stage === want) {
|
|
10406
|
-
path6.push({
|
|
10419
|
+
path6.push({
|
|
10420
|
+
sessionId: n.sessionId,
|
|
10421
|
+
seq: n.seq,
|
|
10422
|
+
stage: n.stage,
|
|
10423
|
+
timestamp: n.timestamp,
|
|
10424
|
+
agentId: n.agentId
|
|
10425
|
+
});
|
|
10407
10426
|
const idx = stages.indexOf(n.stage);
|
|
10408
10427
|
if (idx + 1 < stages.length) {
|
|
10409
10428
|
want = stages[idx + 1];
|
|
@@ -10428,7 +10447,7 @@ var init_stateful = __esm({
|
|
|
10428
10447
|
}
|
|
10429
10448
|
if (taintedRes.size > 0) {
|
|
10430
10449
|
this.tainted.add(idx);
|
|
10431
|
-
for (const r of
|
|
10450
|
+
for (const r of node.resources) this.taintedResources.add(r);
|
|
10432
10451
|
}
|
|
10433
10452
|
}
|
|
10434
10453
|
resourceTainted(resource) {
|
|
@@ -10477,6 +10496,7 @@ var init_stateful = __esm({
|
|
|
10477
10496
|
this.nodes_.push({
|
|
10478
10497
|
seq: Number(raw.seq || 0),
|
|
10479
10498
|
sessionId: String(raw.sessionId || ""),
|
|
10499
|
+
agentId: String(raw.agentId || ""),
|
|
10480
10500
|
actionType: String(raw.actionType || ""),
|
|
10481
10501
|
actionDetail: String(raw.actionDetail || ""),
|
|
10482
10502
|
stage: String(raw.stage || ""),
|
|
@@ -10583,9 +10603,9 @@ var init_chain_state = __esm({
|
|
|
10583
10603
|
delete this.data[agentId];
|
|
10584
10604
|
this._scheduleWrite();
|
|
10585
10605
|
}
|
|
10586
|
-
applyAction(agentId, aNext, sessionId, isError = false) {
|
|
10606
|
+
applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "") {
|
|
10587
10607
|
const t = this.load(agentId) || new StatefulChainTracker(agentId);
|
|
10588
|
-
const r = t.advance({ aNext, sessionId, isError });
|
|
10608
|
+
const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent });
|
|
10589
10609
|
this.save(t);
|
|
10590
10610
|
return r;
|
|
10591
10611
|
}
|
|
@@ -10900,10 +10920,14 @@ async function runAnalysis(input) {
|
|
|
10900
10920
|
const formalSessions = [];
|
|
10901
10921
|
if (input.sessionHistory) {
|
|
10902
10922
|
for (const s of input.sessionHistory) {
|
|
10903
|
-
formalSessions.push({
|
|
10923
|
+
formalSessions.push({
|
|
10924
|
+
sessionId: s.sessionId || "s",
|
|
10925
|
+
...s.agentId ? { agentId: s.agentId } : {},
|
|
10926
|
+
actionHistory: s.actionHistory || []
|
|
10927
|
+
});
|
|
10904
10928
|
}
|
|
10905
10929
|
}
|
|
10906
|
-
formalSessions.push({ sessionId: "current", actionHistory: input.actionHistory });
|
|
10930
|
+
formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
|
|
10907
10931
|
const formalResult = formalEngine.verify(formalSessions, input.aNext);
|
|
10908
10932
|
if (!formalResult.verified) {
|
|
10909
10933
|
const v = formalResult.violations[0];
|
|
@@ -11999,6 +12023,8 @@ async function analyzeRoute(c) {
|
|
|
11999
12023
|
})),
|
|
12000
12024
|
sessionHistory: (req.session_history || []).map((s) => ({
|
|
12001
12025
|
sessionId: s.session_id,
|
|
12026
|
+
// 来源 agent(AgentGate 逐会话带上,用于链路径取证展示;不参与链匹配)
|
|
12027
|
+
...s.agent_id ? { agentId: s.agent_id } : {},
|
|
12002
12028
|
actionHistory: (s.action_history || []).map((h) => ({
|
|
12003
12029
|
actionType: h.action_type,
|
|
12004
12030
|
actionDetail: h.action_detail,
|
|
@@ -12057,10 +12083,14 @@ async function analyzeRoute(c) {
|
|
|
12057
12083
|
if (incEnabled === "1" || incEnabled === "true" || incEnabled === "yes" || incEnabled === "on") {
|
|
12058
12084
|
try {
|
|
12059
12085
|
const store = getChainStateStoreFor(agentId);
|
|
12060
|
-
const inc = store.applyAction(
|
|
12061
|
-
|
|
12062
|
-
actionDetail: req.a_next.action_detail
|
|
12063
|
-
|
|
12086
|
+
const inc = store.applyAction(
|
|
12087
|
+
chainBucket(agentId),
|
|
12088
|
+
{ actionType: req.a_next.action_type, actionDetail: req.a_next.action_detail },
|
|
12089
|
+
req.session_id,
|
|
12090
|
+
Boolean(meta.is_error),
|
|
12091
|
+
agentId
|
|
12092
|
+
// 来源:真实 agent(桶 key 可能是 __system__)
|
|
12093
|
+
);
|
|
12064
12094
|
const judgment = incMatchedToDeny(inc);
|
|
12065
12095
|
if (judgment) {
|
|
12066
12096
|
const layers = [...result.violated_layers];
|
|
@@ -12125,7 +12155,7 @@ function getChainStateStoreFor(_agentId) {
|
|
|
12125
12155
|
}
|
|
12126
12156
|
function incMatchedToDeny(inc) {
|
|
12127
12157
|
if (inc.matched) {
|
|
12128
|
-
const chain = (inc.matched.path || []).map((p) => [p.sessionId, p.seq, p.stage, p.timestamp]);
|
|
12158
|
+
const chain = (inc.matched.path || []).map((p) => [p.sessionId, p.seq, p.stage, p.timestamp, p.agentId ?? null]);
|
|
12129
12159
|
return {
|
|
12130
12160
|
property_id: "cross-" + inc.matched.chainId,
|
|
12131
12161
|
reason: inc.matched.reason,
|
|
@@ -12150,9 +12180,10 @@ async function reviewRoute(c) {
|
|
|
12150
12180
|
const req = ReviewRequestSchema.parse(body);
|
|
12151
12181
|
const agentId = req.agent_id || "default";
|
|
12152
12182
|
const store = getChainStateStoreFor(agentId);
|
|
12153
|
-
|
|
12183
|
+
const bucket = chainBucket(agentId);
|
|
12184
|
+
let tracker = store.load(bucket);
|
|
12154
12185
|
if (!tracker) {
|
|
12155
|
-
tracker = new StatefulChainTracker(
|
|
12186
|
+
tracker = new StatefulChainTracker(bucket);
|
|
12156
12187
|
}
|
|
12157
12188
|
if (req.db_path && !pathWithin(req.db_path, reviewRoots())) {
|
|
12158
12189
|
return c.json({
|
|
@@ -2249,7 +2249,7 @@ function _scenarioRulesToDefaults() {
|
|
|
2249
2249
|
if (!existsSync5(scenDir)) return out;
|
|
2250
2250
|
let entries;
|
|
2251
2251
|
try {
|
|
2252
|
-
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
2252
|
+
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("__")).map((d) => d.name);
|
|
2253
2253
|
} catch {
|
|
2254
2254
|
return out;
|
|
2255
2255
|
}
|
|
@@ -8369,7 +8369,7 @@ function markIntegrity(actionDetail) {
|
|
|
8369
8369
|
}
|
|
8370
8370
|
return { integrity: "medium", isLowSource: false };
|
|
8371
8371
|
}
|
|
8372
|
-
function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
8372
|
+
function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "") {
|
|
8373
8373
|
const { integrity, isLowSource } = markIntegrity(actionDetail);
|
|
8374
8374
|
return {
|
|
8375
8375
|
sessionId,
|
|
@@ -8377,13 +8377,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
|
8377
8377
|
actionType,
|
|
8378
8378
|
actionDetail,
|
|
8379
8379
|
stage: markStage(actionDetail),
|
|
8380
|
+
agentId: agentId || void 0,
|
|
8380
8381
|
resources: extractResources(actionDetail),
|
|
8381
8382
|
integrity,
|
|
8382
8383
|
isLowSource,
|
|
8383
8384
|
timestamp: timestamp || void 0
|
|
8384
8385
|
};
|
|
8385
8386
|
}
|
|
8386
|
-
function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
8387
|
+
function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
|
|
8387
8388
|
const nodes = [];
|
|
8388
8389
|
const edges = [];
|
|
8389
8390
|
const stageFlags = /* @__PURE__ */ new Set();
|
|
@@ -8393,18 +8394,20 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
|
8393
8394
|
if (ad) details.push({
|
|
8394
8395
|
actionType: String(a.actionType || ""),
|
|
8395
8396
|
actionDetail: ad,
|
|
8396
|
-
calledAt: a.calledAt || void 0
|
|
8397
|
+
calledAt: a.calledAt || void 0,
|
|
8398
|
+
agentId: a.agentId || agentId || void 0
|
|
8397
8399
|
});
|
|
8398
8400
|
}
|
|
8399
8401
|
if (aNext) {
|
|
8400
8402
|
details.push({
|
|
8401
8403
|
actionType: String(aNext.actionType || ""),
|
|
8402
8404
|
actionDetail: String(aNext.actionDetail || ""),
|
|
8403
|
-
calledAt: aNext.calledAt || void 0
|
|
8405
|
+
calledAt: aNext.calledAt || void 0,
|
|
8406
|
+
agentId: aNext.agentId || agentId || void 0
|
|
8404
8407
|
});
|
|
8405
8408
|
}
|
|
8406
8409
|
details.forEach((d, seq) => {
|
|
8407
|
-
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt);
|
|
8410
|
+
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
|
|
8408
8411
|
nodes.push(node);
|
|
8409
8412
|
if (node.stage) stageFlags.add(node.stage);
|
|
8410
8413
|
});
|
|
@@ -8421,7 +8424,7 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
8421
8424
|
}
|
|
8422
8425
|
for (const s of sessions) {
|
|
8423
8426
|
const sid = String(s.sessionId || "s");
|
|
8424
|
-
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid));
|
|
8427
|
+
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
|
|
8425
8428
|
}
|
|
8426
8429
|
if (aNext) {
|
|
8427
8430
|
const last = mg.sessions[mg.sessions.length - 1];
|
|
@@ -8431,7 +8434,8 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
8431
8434
|
last.nodes.length,
|
|
8432
8435
|
String(aNext.actionType || ""),
|
|
8433
8436
|
String(aNext.actionDetail || ""),
|
|
8434
|
-
aNext.calledAt || void 0
|
|
8437
|
+
aNext.calledAt || void 0,
|
|
8438
|
+
aNext.agentId || ""
|
|
8435
8439
|
));
|
|
8436
8440
|
if (last.nodes.length > 1) {
|
|
8437
8441
|
last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
|
|
@@ -9325,10 +9329,14 @@ async function runAnalysis(input) {
|
|
|
9325
9329
|
const formalSessions = [];
|
|
9326
9330
|
if (input.sessionHistory) {
|
|
9327
9331
|
for (const s of input.sessionHistory) {
|
|
9328
|
-
formalSessions.push({
|
|
9332
|
+
formalSessions.push({
|
|
9333
|
+
sessionId: s.sessionId || "s",
|
|
9334
|
+
...s.agentId ? { agentId: s.agentId } : {},
|
|
9335
|
+
actionHistory: s.actionHistory || []
|
|
9336
|
+
});
|
|
9329
9337
|
}
|
|
9330
9338
|
}
|
|
9331
|
-
formalSessions.push({ sessionId: "current", actionHistory: input.actionHistory });
|
|
9339
|
+
formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
|
|
9332
9340
|
const formalResult = formalEngine.verify(formalSessions, input.aNext);
|
|
9333
9341
|
if (!formalResult.verified) {
|
|
9334
9342
|
const v = formalResult.violations[0];
|
package/dist/server.js
CHANGED
|
@@ -1186,6 +1186,12 @@ function agentInflight() {
|
|
|
1186
1186
|
function boundAgentOf(principal) {
|
|
1187
1187
|
return principal.startsWith("agent:") ? principal.slice("agent:".length) : "";
|
|
1188
1188
|
}
|
|
1189
|
+
function chainScope() {
|
|
1190
|
+
return (env("AGENT_MOSS_CHAIN_SCOPE", "system") || "system").toLowerCase();
|
|
1191
|
+
}
|
|
1192
|
+
function chainBucket(agentId = "") {
|
|
1193
|
+
return chainScope() === "agent" ? agentId || "default" : "__system__";
|
|
1194
|
+
}
|
|
1189
1195
|
function rateLimitQps() {
|
|
1190
1196
|
return envInt("AGENT_MOSS_RATE_LIMIT_QPS", 100);
|
|
1191
1197
|
}
|
|
@@ -2749,7 +2755,7 @@ function _scenarioRulesToDefaults() {
|
|
|
2749
2755
|
if (!existsSync7(scenDir)) return out;
|
|
2750
2756
|
let entries;
|
|
2751
2757
|
try {
|
|
2752
|
-
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
2758
|
+
entries = readdirSync4(scenDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith("__")).map((d) => d.name);
|
|
2753
2759
|
} catch {
|
|
2754
2760
|
return out;
|
|
2755
2761
|
}
|
|
@@ -8864,7 +8870,7 @@ function markIntegrity(actionDetail) {
|
|
|
8864
8870
|
}
|
|
8865
8871
|
return { integrity: "medium", isLowSource: false };
|
|
8866
8872
|
}
|
|
8867
|
-
function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
8873
|
+
function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "") {
|
|
8868
8874
|
const { integrity, isLowSource } = markIntegrity(actionDetail);
|
|
8869
8875
|
return {
|
|
8870
8876
|
sessionId,
|
|
@@ -8872,13 +8878,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp) {
|
|
|
8872
8878
|
actionType,
|
|
8873
8879
|
actionDetail,
|
|
8874
8880
|
stage: markStage(actionDetail),
|
|
8881
|
+
agentId: agentId || void 0,
|
|
8875
8882
|
resources: extractResources(actionDetail),
|
|
8876
8883
|
integrity,
|
|
8877
8884
|
isLowSource,
|
|
8878
8885
|
timestamp: timestamp || void 0
|
|
8879
8886
|
};
|
|
8880
8887
|
}
|
|
8881
|
-
function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
8888
|
+
function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
|
|
8882
8889
|
const nodes = [];
|
|
8883
8890
|
const edges = [];
|
|
8884
8891
|
const stageFlags = /* @__PURE__ */ new Set();
|
|
@@ -8888,18 +8895,20 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current") {
|
|
|
8888
8895
|
if (ad) details.push({
|
|
8889
8896
|
actionType: String(a.actionType || ""),
|
|
8890
8897
|
actionDetail: ad,
|
|
8891
|
-
calledAt: a.calledAt || void 0
|
|
8898
|
+
calledAt: a.calledAt || void 0,
|
|
8899
|
+
agentId: a.agentId || agentId || void 0
|
|
8892
8900
|
});
|
|
8893
8901
|
}
|
|
8894
8902
|
if (aNext) {
|
|
8895
8903
|
details.push({
|
|
8896
8904
|
actionType: String(aNext.actionType || ""),
|
|
8897
8905
|
actionDetail: String(aNext.actionDetail || ""),
|
|
8898
|
-
calledAt: aNext.calledAt || void 0
|
|
8906
|
+
calledAt: aNext.calledAt || void 0,
|
|
8907
|
+
agentId: aNext.agentId || agentId || void 0
|
|
8899
8908
|
});
|
|
8900
8909
|
}
|
|
8901
8910
|
details.forEach((d, seq) => {
|
|
8902
|
-
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt);
|
|
8911
|
+
const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
|
|
8903
8912
|
nodes.push(node);
|
|
8904
8913
|
if (node.stage) stageFlags.add(node.stage);
|
|
8905
8914
|
});
|
|
@@ -8916,7 +8925,7 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
8916
8925
|
}
|
|
8917
8926
|
for (const s of sessions) {
|
|
8918
8927
|
const sid = String(s.sessionId || "s");
|
|
8919
|
-
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid));
|
|
8928
|
+
mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
|
|
8920
8929
|
}
|
|
8921
8930
|
if (aNext) {
|
|
8922
8931
|
const last = mg.sessions[mg.sessions.length - 1];
|
|
@@ -8926,7 +8935,8 @@ function buildMultiSessionGraph(sessions, aNext) {
|
|
|
8926
8935
|
last.nodes.length,
|
|
8927
8936
|
String(aNext.actionType || ""),
|
|
8928
8937
|
String(aNext.actionDetail || ""),
|
|
8929
|
-
aNext.calledAt || void 0
|
|
8938
|
+
aNext.calledAt || void 0,
|
|
8939
|
+
aNext.agentId || ""
|
|
8930
8940
|
));
|
|
8931
8941
|
if (last.nodes.length > 1) {
|
|
8932
8942
|
last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
|
|
@@ -9713,8 +9723,8 @@ var init_stateful = __esm({
|
|
|
9713
9723
|
}
|
|
9714
9724
|
/** 增量推进:把当前动作追加到时间线 → 链指针推进 → 判定。 */
|
|
9715
9725
|
advance(args) {
|
|
9716
|
-
const { aNext, sessionId = "current", isError = false } = args;
|
|
9717
|
-
const node = this.appendNode(aNext, sessionId, isError);
|
|
9726
|
+
const { aNext, sessionId = "current", isError = false, agentId = "" } = args;
|
|
9727
|
+
const node = this.appendNode(aNext, sessionId, isError, agentId);
|
|
9718
9728
|
if (!node) {
|
|
9719
9729
|
return { seq: this.seqNext, node: null, matched: null, pendingPrefixes: this.pendingPrefixes, exfil: [], shouldBlock: false };
|
|
9720
9730
|
}
|
|
@@ -9734,7 +9744,7 @@ var init_stateful = __esm({
|
|
|
9734
9744
|
}
|
|
9735
9745
|
};
|
|
9736
9746
|
}
|
|
9737
|
-
appendNode(action, sessionId, isError = false) {
|
|
9747
|
+
appendNode(action, sessionId, isError = false, agentId = "") {
|
|
9738
9748
|
const ad = String(action.actionDetail || "");
|
|
9739
9749
|
const at = String(action.actionType || "");
|
|
9740
9750
|
if (!ad) return null;
|
|
@@ -9751,6 +9761,7 @@ var init_stateful = __esm({
|
|
|
9751
9761
|
resources: extractResources2(ad),
|
|
9752
9762
|
instances: extractInstances(ad, stage),
|
|
9753
9763
|
isError,
|
|
9764
|
+
agentId: String(action.agentId || agentId || ""),
|
|
9754
9765
|
lifecycle: lifecycleFor(ad, stage, isError),
|
|
9755
9766
|
timestamp: typeof action.calledAt === "string" ? action.calledAt : _StatefulChainTracker.now()
|
|
9756
9767
|
};
|
|
@@ -9888,7 +9899,13 @@ var init_stateful = __esm({
|
|
|
9888
9899
|
let want = stages[0];
|
|
9889
9900
|
for (const n of this.nodes_) {
|
|
9890
9901
|
if (n.stage === want) {
|
|
9891
|
-
path6.push({
|
|
9902
|
+
path6.push({
|
|
9903
|
+
sessionId: n.sessionId,
|
|
9904
|
+
seq: n.seq,
|
|
9905
|
+
stage: n.stage,
|
|
9906
|
+
timestamp: n.timestamp,
|
|
9907
|
+
agentId: n.agentId
|
|
9908
|
+
});
|
|
9892
9909
|
const idx = stages.indexOf(n.stage);
|
|
9893
9910
|
if (idx + 1 < stages.length) {
|
|
9894
9911
|
want = stages[idx + 1];
|
|
@@ -9913,7 +9930,7 @@ var init_stateful = __esm({
|
|
|
9913
9930
|
}
|
|
9914
9931
|
if (taintedRes.size > 0) {
|
|
9915
9932
|
this.tainted.add(idx);
|
|
9916
|
-
for (const r of
|
|
9933
|
+
for (const r of node.resources) this.taintedResources.add(r);
|
|
9917
9934
|
}
|
|
9918
9935
|
}
|
|
9919
9936
|
resourceTainted(resource) {
|
|
@@ -9962,6 +9979,7 @@ var init_stateful = __esm({
|
|
|
9962
9979
|
this.nodes_.push({
|
|
9963
9980
|
seq: Number(raw.seq || 0),
|
|
9964
9981
|
sessionId: String(raw.sessionId || ""),
|
|
9982
|
+
agentId: String(raw.agentId || ""),
|
|
9965
9983
|
actionType: String(raw.actionType || ""),
|
|
9966
9984
|
actionDetail: String(raw.actionDetail || ""),
|
|
9967
9985
|
stage: String(raw.stage || ""),
|
|
@@ -10068,9 +10086,9 @@ var init_chain_state = __esm({
|
|
|
10068
10086
|
delete this.data[agentId];
|
|
10069
10087
|
this._scheduleWrite();
|
|
10070
10088
|
}
|
|
10071
|
-
applyAction(agentId, aNext, sessionId, isError = false) {
|
|
10089
|
+
applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "") {
|
|
10072
10090
|
const t = this.load(agentId) || new StatefulChainTracker(agentId);
|
|
10073
|
-
const r = t.advance({ aNext, sessionId, isError });
|
|
10091
|
+
const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent });
|
|
10074
10092
|
this.save(t);
|
|
10075
10093
|
return r;
|
|
10076
10094
|
}
|
|
@@ -10385,10 +10403,14 @@ async function runAnalysis(input) {
|
|
|
10385
10403
|
const formalSessions = [];
|
|
10386
10404
|
if (input.sessionHistory) {
|
|
10387
10405
|
for (const s of input.sessionHistory) {
|
|
10388
|
-
formalSessions.push({
|
|
10406
|
+
formalSessions.push({
|
|
10407
|
+
sessionId: s.sessionId || "s",
|
|
10408
|
+
...s.agentId ? { agentId: s.agentId } : {},
|
|
10409
|
+
actionHistory: s.actionHistory || []
|
|
10410
|
+
});
|
|
10389
10411
|
}
|
|
10390
10412
|
}
|
|
10391
|
-
formalSessions.push({ sessionId: "current", actionHistory: input.actionHistory });
|
|
10413
|
+
formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
|
|
10392
10414
|
const formalResult = formalEngine.verify(formalSessions, input.aNext);
|
|
10393
10415
|
if (!formalResult.verified) {
|
|
10394
10416
|
const v = formalResult.violations[0];
|
|
@@ -10756,6 +10778,8 @@ var AnalyzeRequestSchema = z.object({
|
|
|
10756
10778
|
action_history: z.array(ActionItemSchema).default([]).describe("Historical action sequence"),
|
|
10757
10779
|
session_history: z.array(z.object({
|
|
10758
10780
|
session_id: z.string(),
|
|
10781
|
+
/** 来源 agent(AgentGate 逐会话带上):记录在链路径里供告警/取证,不参与链匹配。 */
|
|
10782
|
+
agent_id: z.string().optional(),
|
|
10759
10783
|
action_history: z.array(ActionItemSchema).default([])
|
|
10760
10784
|
})).default([]).describe("Multi-session historical actions (optional): for L2.2 formal engine cross-session combo-chain / sensitive-data-flow verification. Provided by caller (incl. future agentgate)."),
|
|
10761
10785
|
a_next: ActionItemSchema.describe("Next action to be executed"),
|
|
@@ -11670,6 +11694,8 @@ async function analyzeRoute(c) {
|
|
|
11670
11694
|
})),
|
|
11671
11695
|
sessionHistory: (req.session_history || []).map((s) => ({
|
|
11672
11696
|
sessionId: s.session_id,
|
|
11697
|
+
// 来源 agent(AgentGate 逐会话带上,用于链路径取证展示;不参与链匹配)
|
|
11698
|
+
...s.agent_id ? { agentId: s.agent_id } : {},
|
|
11673
11699
|
actionHistory: (s.action_history || []).map((h) => ({
|
|
11674
11700
|
actionType: h.action_type,
|
|
11675
11701
|
actionDetail: h.action_detail,
|
|
@@ -11728,10 +11754,14 @@ async function analyzeRoute(c) {
|
|
|
11728
11754
|
if (incEnabled === "1" || incEnabled === "true" || incEnabled === "yes" || incEnabled === "on") {
|
|
11729
11755
|
try {
|
|
11730
11756
|
const store = getChainStateStoreFor(agentId);
|
|
11731
|
-
const inc = store.applyAction(
|
|
11732
|
-
|
|
11733
|
-
actionDetail: req.a_next.action_detail
|
|
11734
|
-
|
|
11757
|
+
const inc = store.applyAction(
|
|
11758
|
+
chainBucket(agentId),
|
|
11759
|
+
{ actionType: req.a_next.action_type, actionDetail: req.a_next.action_detail },
|
|
11760
|
+
req.session_id,
|
|
11761
|
+
Boolean(meta.is_error),
|
|
11762
|
+
agentId
|
|
11763
|
+
// 来源:真实 agent(桶 key 可能是 __system__)
|
|
11764
|
+
);
|
|
11735
11765
|
const judgment = incMatchedToDeny(inc);
|
|
11736
11766
|
if (judgment) {
|
|
11737
11767
|
const layers = [...result.violated_layers];
|
|
@@ -11797,7 +11827,7 @@ function getChainStateStoreFor(_agentId) {
|
|
|
11797
11827
|
}
|
|
11798
11828
|
function incMatchedToDeny(inc) {
|
|
11799
11829
|
if (inc.matched) {
|
|
11800
|
-
const chain = (inc.matched.path || []).map((p) => [p.sessionId, p.seq, p.stage, p.timestamp]);
|
|
11830
|
+
const chain = (inc.matched.path || []).map((p) => [p.sessionId, p.seq, p.stage, p.timestamp, p.agentId ?? null]);
|
|
11801
11831
|
return {
|
|
11802
11832
|
property_id: "cross-" + inc.matched.chainId,
|
|
11803
11833
|
reason: inc.matched.reason,
|
|
@@ -11822,9 +11852,10 @@ async function reviewRoute(c) {
|
|
|
11822
11852
|
const req = ReviewRequestSchema.parse(body);
|
|
11823
11853
|
const agentId = req.agent_id || "default";
|
|
11824
11854
|
const store = getChainStateStoreFor(agentId);
|
|
11825
|
-
|
|
11855
|
+
const bucket = chainBucket(agentId);
|
|
11856
|
+
let tracker = store.load(bucket);
|
|
11826
11857
|
if (!tracker) {
|
|
11827
|
-
tracker = new StatefulChainTracker(
|
|
11858
|
+
tracker = new StatefulChainTracker(bucket);
|
|
11828
11859
|
}
|
|
11829
11860
|
if (req.db_path && !pathWithin(req.db_path, reviewRoots())) {
|
|
11830
11861
|
return c.json({
|