@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 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({ sessionId: n.sessionId, seq: n.seq, stage: n.stage, timestamp: n.timestamp });
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 taintedRes) this.taintedResources.add(r);
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({ sessionId: s.sessionId || "s", actionHistory: s.actionHistory || [] });
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(agentId, {
12061
- actionType: req.a_next.action_type,
12062
- actionDetail: req.a_next.action_detail
12063
- }, req.session_id, Boolean(meta.is_error));
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
- let tracker = store.load(agentId);
12183
+ const bucket = chainBucket(agentId);
12184
+ let tracker = store.load(bucket);
12154
12185
  if (!tracker) {
12155
- tracker = new StatefulChainTracker(agentId);
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({ sessionId: s.sessionId || "s", actionHistory: s.actionHistory || [] });
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({ sessionId: n.sessionId, seq: n.seq, stage: n.stage, timestamp: n.timestamp });
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 taintedRes) this.taintedResources.add(r);
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({ sessionId: s.sessionId || "s", actionHistory: s.actionHistory || [] });
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(agentId, {
11732
- actionType: req.a_next.action_type,
11733
- actionDetail: req.a_next.action_detail
11734
- }, req.session_id, Boolean(meta.is_error));
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
- let tracker = store.load(agentId);
11855
+ const bucket = chainBucket(agentId);
11856
+ let tracker = store.load(bucket);
11826
11857
  if (!tracker) {
11827
- tracker = new StatefulChainTracker(agentId);
11858
+ tracker = new StatefulChainTracker(bucket);
11828
11859
  }
11829
11860
  if (req.db_path && !pathWithin(req.db_path, reviewRoots())) {
11830
11861
  return c.json({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenhkl/agent-moss",
3
- "version": "0.17.6",
3
+ "version": "0.17.7",
4
4
  "description": "Multi-layer security analysis engine for AI agents (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",