@kenhkl/agent-moss 0.17.8 → 0.17.10

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
@@ -1246,31 +1246,42 @@ function hardenExistingPaths() {
1246
1246
  function chainDetailMode() {
1247
1247
  return (env("AGENT_MOSS_CHAIN_DETAIL", "redacted") || "redacted").toLowerCase();
1248
1248
  }
1249
- function redactChain(chain, currentSessionId) {
1249
+ function redactChain(chain, currentInstanceId = "", currentSessionId = "") {
1250
1250
  if (!chain || chain.length === 0) return [];
1251
1251
  if (chainDetailMode() === "full") return [...chain];
1252
1252
  return chain.map((step) => {
1253
1253
  if (Array.isArray(step) && step.length >= 3) {
1254
1254
  const [sid, seq, , ts] = step;
1255
- if (String(sid) === String(currentSessionId)) return [...step];
1255
+ const inst = step.length > 5 ? String(step[5] ?? "") : "";
1256
+ const sameInstance = !!(inst && currentInstanceId && inst === String(currentInstanceId));
1257
+ const sameSessionFallback = !inst && !!currentSessionId && String(sid) === String(currentSessionId);
1258
+ if (sameInstance || sameSessionFallback) return [...step];
1256
1259
  return ["<other-session>", seq, "<\u5DF2\u9690\u85CF>", ts ?? ""];
1257
1260
  }
1258
1261
  return step;
1259
1262
  });
1260
1263
  }
1261
- function redactGraph(graph, currentSessionId) {
1264
+ function redactGraph(graph, currentInstanceId = "", currentSessionId = "") {
1262
1265
  if (!graph) return null;
1263
1266
  if (chainDetailMode() === "full") return graph;
1264
1267
  const nodes = (graph.nodes || []).map((n) => {
1265
1268
  const m = { ...n };
1266
- if (String(m.session_id ?? "") !== String(currentSessionId)) {
1269
+ const inst = String(m.instance_id ?? "") || "";
1270
+ const sid = String(m.session_id ?? "") || "";
1271
+ const sameInstance = !!(inst && currentInstanceId && inst === String(currentInstanceId));
1272
+ const sameSessionFallback = !inst && !!currentSessionId && sid === String(currentSessionId);
1273
+ if (!(sameInstance || sameSessionFallback)) {
1267
1274
  m.session_id = "<other-session>";
1268
1275
  m.action_detail = "<\u5DF2\u9690\u85CF>";
1269
1276
  m.resources = [];
1270
1277
  }
1271
1278
  return m;
1272
1279
  });
1273
- return { nodes, edges: graph.edges || [] };
1280
+ const out = { nodes, edges: graph.edges || [] };
1281
+ for (const key of ["property_id", "property_short", "property_name", "property_expression"]) {
1282
+ if (graph[key] !== void 0) out[key] = graph[key];
1283
+ }
1284
+ return out;
1274
1285
  }
1275
1286
  function sessionSweepThreshold() {
1276
1287
  return envInt("AGENT_MOSS_SESSION_SWEEP_THRESHOLD", 50);
@@ -1433,6 +1444,8 @@ var init_models = __esm({
1433
1444
  session_id: z.string(),
1434
1445
  /** 来源 agent(AgentGate 逐会话带上):记录在链路径里供告警/取证,不参与链匹配。 */
1435
1446
  agent_id: z.string().optional(),
1447
+ /** 来源实例:仅用于展示层脱敏(同实例不隐藏),不参与链匹配。 */
1448
+ instance_id: z.string().optional(),
1436
1449
  action_history: z.array(ActionItemSchema).default([])
1437
1450
  })).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)."),
1438
1451
  a_next: ActionItemSchema.describe("Next action to be executed"),
@@ -1440,6 +1453,7 @@ var init_models = __esm({
1440
1453
  os_type: z.string().default("").describe("OS type: 'linux', 'windows', or empty for auto-detect"),
1441
1454
  cwd: z.string().default("").describe("Current working directory"),
1442
1455
  agent_id: z.string().default("").describe("Caller agent identifier, e.g. 'xiaoo' / 'opencode' / 'opendesk'. Empty = generic mode (no agent-specific rules)."),
1456
+ instance_id: z.string().default("").describe("Agent installation/instance identifier. Used only for display-layer redaction: nodes from the same instance are returned unredacted. Does not affect detection."),
1443
1457
  metadata: z.record(z.unknown()).optional().describe("Extended metadata")
1444
1458
  });
1445
1459
  AnalyzeResponseSchema = z.object({
@@ -1477,7 +1491,9 @@ var init_models = __esm({
1477
1491
  // 节点在性质中的角色:source/carrier/sink(P2)或阶段名(P1)
1478
1492
  role: z.string().optional(),
1479
1493
  // 是否为违例见证节点(当前动作补全链 / 触发外传)
1480
- witness: z.boolean().optional()
1494
+ witness: z.boolean().optional(),
1495
+ // 来源实例(仅展示层脱敏:同实例不隐藏)
1496
+ instance_id: z.string().optional()
1481
1497
  })
1482
1498
  ),
1483
1499
  edges: z.array(
@@ -9436,7 +9452,7 @@ function markIntegrity(actionDetail) {
9436
9452
  }
9437
9453
  return { integrity: "medium", isLowSource: false };
9438
9454
  }
9439
- function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "") {
9455
+ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "", instanceId = "") {
9440
9456
  const { integrity, isLowSource } = markIntegrity(actionDetail);
9441
9457
  return {
9442
9458
  sessionId,
@@ -9445,13 +9461,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId =
9445
9461
  actionDetail,
9446
9462
  stage: markStage(actionDetail),
9447
9463
  agentId: agentId || void 0,
9464
+ instanceId: instanceId || void 0,
9448
9465
  resources: extractResources(actionDetail),
9449
9466
  integrity,
9450
9467
  isLowSource,
9451
9468
  timestamp: timestamp || void 0
9452
9469
  };
9453
9470
  }
9454
- function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
9471
+ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "", instanceId = "") {
9455
9472
  const nodes = [];
9456
9473
  const edges = [];
9457
9474
  const stageFlags = /* @__PURE__ */ new Set();
@@ -9462,7 +9479,8 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
9462
9479
  actionType: String(a.actionType || ""),
9463
9480
  actionDetail: ad,
9464
9481
  calledAt: a.calledAt || void 0,
9465
- agentId: a.agentId || agentId || void 0
9482
+ agentId: a.agentId || agentId || void 0,
9483
+ instanceId: a.instanceId || instanceId || void 0
9466
9484
  });
9467
9485
  }
9468
9486
  if (aNext) {
@@ -9470,11 +9488,12 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
9470
9488
  actionType: String(aNext.actionType || ""),
9471
9489
  actionDetail: String(aNext.actionDetail || ""),
9472
9490
  calledAt: aNext.calledAt || void 0,
9473
- agentId: aNext.agentId || agentId || void 0
9491
+ agentId: aNext.agentId || agentId || void 0,
9492
+ instanceId: aNext.instanceId || instanceId || void 0
9474
9493
  });
9475
9494
  }
9476
9495
  details.forEach((d, seq) => {
9477
- const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
9496
+ const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "", d.instanceId || "");
9478
9497
  nodes.push(node);
9479
9498
  if (node.stage) stageFlags.add(node.stage);
9480
9499
  });
@@ -9486,12 +9505,18 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
9486
9505
  function buildMultiSessionGraph(sessions, aNext) {
9487
9506
  const mg = { sessions: [], crossEdges: [] };
9488
9507
  if (!sessions || sessions.length === 0) {
9489
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
9508
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext?.instanceId || ""));
9490
9509
  return mg;
9491
9510
  }
9492
9511
  for (const s of sessions) {
9493
9512
  const sid = String(s.sessionId || "s");
9494
- mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
9513
+ mg.sessions.push(buildSessionGraph(
9514
+ s.actionHistory || [],
9515
+ void 0,
9516
+ sid,
9517
+ s.agentId || "",
9518
+ s.instanceId || ""
9519
+ ));
9495
9520
  }
9496
9521
  if (aNext) {
9497
9522
  const last = mg.sessions[mg.sessions.length - 1];
@@ -9502,13 +9527,14 @@ function buildMultiSessionGraph(sessions, aNext) {
9502
9527
  String(aNext.actionType || ""),
9503
9528
  String(aNext.actionDetail || ""),
9504
9529
  aNext.calledAt || void 0,
9505
- aNext.agentId || ""
9530
+ aNext.agentId || "",
9531
+ aNext.instanceId || ""
9506
9532
  ));
9507
9533
  if (last.nodes.length > 1) {
9508
9534
  last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
9509
9535
  }
9510
9536
  } else {
9511
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
9537
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext.instanceId || ""));
9512
9538
  }
9513
9539
  }
9514
9540
  addCrossDataEdges(mg);
@@ -9572,7 +9598,8 @@ function graphFromPath(nodes, path6, edgeType = "next", propertyMeta, roles, wit
9572
9598
  seq: item.seq,
9573
9599
  stage: n ? n.stage : "",
9574
9600
  action_detail: n ? n.actionDetail : item.detail,
9575
- resources: n ? [...n.resources].sort() : []
9601
+ resources: n ? [...n.resources].sort() : [],
9602
+ instance_id: n ? n.instanceId || "" : ""
9576
9603
  });
9577
9604
  if (gNodes.length > 1) {
9578
9605
  gEdges.push({ from: gNodes.length - 2, to: gNodes.length - 1, type: edgeType });
@@ -9740,7 +9767,8 @@ function checkSensitiveDataFlow(graph) {
9740
9767
  stage: n.stage,
9741
9768
  action_detail: n.actionDetail,
9742
9769
  resources: [...n.resources].sort(),
9743
- role
9770
+ role,
9771
+ instance_id: n.instanceId || ""
9744
9772
  });
9745
9773
  if (k > 0) {
9746
9774
  const prev = chain[k - 1];
@@ -10383,7 +10411,7 @@ var init_stateful = __esm({
10383
10411
  for (const s of sessions || []) {
10384
10412
  const sid = String(s.sessionId || "s");
10385
10413
  for (const a of s.actionHistory || []) {
10386
- const node = this.appendNode(a, sid);
10414
+ const node = this.appendNode(a, sid, false, s.agentId || "", s.instanceId || "");
10387
10415
  if (!node) {
10388
10416
  continue;
10389
10417
  }
@@ -10397,8 +10425,8 @@ var init_stateful = __esm({
10397
10425
  }
10398
10426
  /** 增量推进:把当前动作追加到时间线 → 链指针推进 → 判定。 */
10399
10427
  advance(args) {
10400
- const { aNext, sessionId = "current", isError = false, agentId = "" } = args;
10401
- const node = this.appendNode(aNext, sessionId, isError, agentId);
10428
+ const { aNext, sessionId = "current", isError = false, agentId = "", instanceId = "" } = args;
10429
+ const node = this.appendNode(aNext, sessionId, isError, agentId, instanceId);
10402
10430
  if (!node) {
10403
10431
  return { seq: this.seqNext, node: null, matched: null, pendingPrefixes: this.pendingPrefixes, exfil: [], shouldBlock: false };
10404
10432
  }
@@ -10418,7 +10446,7 @@ var init_stateful = __esm({
10418
10446
  }
10419
10447
  };
10420
10448
  }
10421
- appendNode(action, sessionId, isError = false, agentId = "") {
10449
+ appendNode(action, sessionId, isError = false, agentId = "", instanceId = "") {
10422
10450
  const ad = String(action.actionDetail || "");
10423
10451
  const at = String(action.actionType || "");
10424
10452
  if (!ad) return null;
@@ -10436,6 +10464,7 @@ var init_stateful = __esm({
10436
10464
  instances: extractInstances(ad, stage),
10437
10465
  isError,
10438
10466
  agentId: String(action.agentId || agentId || ""),
10467
+ instanceId: String(action.instanceId || instanceId || ""),
10439
10468
  lifecycle: lifecycleFor(ad, stage, isError),
10440
10469
  timestamp: typeof action.calledAt === "string" ? action.calledAt : _StatefulChainTracker.now()
10441
10470
  };
@@ -10579,7 +10608,8 @@ var init_stateful = __esm({
10579
10608
  seq: n.seq,
10580
10609
  stage: n.stage,
10581
10610
  timestamp: n.timestamp,
10582
- agentId: n.agentId
10611
+ agentId: n.agentId,
10612
+ instanceId: n.instanceId
10583
10613
  });
10584
10614
  const idx = stages.indexOf(n.stage);
10585
10615
  if (idx + 1 < stages.length) {
@@ -10602,7 +10632,8 @@ var init_stateful = __esm({
10602
10632
  stage: p.stage,
10603
10633
  action_detail: n ? n.actionDetail : "",
10604
10634
  resources: n ? [...n.resources].sort() : [],
10605
- role: stages[i] || ""
10635
+ role: stages[i] || "",
10636
+ instance_id: p.instanceId || ""
10606
10637
  };
10607
10638
  });
10608
10639
  const gEdges = [];
@@ -10670,7 +10701,7 @@ var init_stateful = __esm({
10670
10701
  risk_level: "critical",
10671
10702
  path: chain.map((j) => {
10672
10703
  const n = this.nodes_[j];
10673
- return [n.sessionId, n.seq, n.actionDetail.slice(0, 60), n.timestamp];
10704
+ return [n.sessionId, n.seq, n.actionDetail.slice(0, 60), n.timestamp, null, n.instanceId];
10674
10705
  }),
10675
10706
  graph: this.taintGraph(chain)
10676
10707
  }];
@@ -10702,7 +10733,8 @@ var init_stateful = __esm({
10702
10733
  stage: n.stage,
10703
10734
  action_detail: n.actionDetail,
10704
10735
  resources: [...n.resources].sort(),
10705
- role
10736
+ role,
10737
+ instance_id: n.instanceId
10706
10738
  });
10707
10739
  if (k > 0) {
10708
10740
  const prev = chain[k - 1];
@@ -10774,6 +10806,8 @@ var init_stateful = __esm({
10774
10806
  seq: Number(raw.seq || 0),
10775
10807
  sessionId: String(raw.sessionId || ""),
10776
10808
  agentId: String(raw.agentId || ""),
10809
+ instanceId: String(raw.instanceId || ""),
10810
+ // 旧快照无此字段 → 空
10777
10811
  actionType: String(raw.actionType || ""),
10778
10812
  actionDetail: String(raw.actionDetail || ""),
10779
10813
  stage: String(raw.stage || ""),
@@ -10918,9 +10952,9 @@ var init_chain_state = __esm({
10918
10952
  delete this.data[agentId];
10919
10953
  this._scheduleWrite();
10920
10954
  }
10921
- applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "") {
10955
+ applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "", instanceId = "") {
10922
10956
  const t = this.load(agentId) || new StatefulChainTracker(agentId);
10923
- const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent });
10957
+ const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent, instanceId });
10924
10958
  this.save(t);
10925
10959
  return r;
10926
10960
  }
@@ -11238,12 +11272,21 @@ async function runAnalysis(input) {
11238
11272
  formalSessions.push({
11239
11273
  sessionId: s.sessionId || "s",
11240
11274
  ...s.agentId ? { agentId: s.agentId } : {},
11275
+ ...s.instanceId ? { instanceId: s.instanceId } : {},
11241
11276
  actionHistory: s.actionHistory || []
11242
11277
  });
11243
11278
  }
11244
11279
  }
11245
- formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
11246
- const formalResult = formalEngine.verify(formalSessions, input.aNext);
11280
+ formalSessions.push({
11281
+ sessionId: "current",
11282
+ agentId: input.agentId,
11283
+ instanceId: input.instanceId || "",
11284
+ actionHistory: input.actionHistory
11285
+ });
11286
+ const formalResult = formalEngine.verify(formalSessions, {
11287
+ ...input.aNext,
11288
+ instanceId: input.instanceId || ""
11289
+ });
11247
11290
  if (!formalResult.verified) {
11248
11291
  const v = formalResult.violations[0];
11249
11292
  if (isFormalObserveMode()) {
@@ -12327,6 +12370,9 @@ async function analyzeRoute(c) {
12327
12370
  `[AgentMoss] \u26A0\uFE0F \u8DE8\u4F1A\u8BDD\u6279\u91CF\u8BBF\u95EE: key=${_sweepKey} \u7A97\u53E3\u5185 ${_sweepN} \u4E2A\u4E0D\u540C session\uFF08\u9608\u503C ${sessionSweepThreshold()}\uFF09`
12328
12371
  );
12329
12372
  }
12373
+ const instanceId = String(
12374
+ req.instance_id || req.metadata?.instance_id || ""
12375
+ );
12330
12376
  const result = await analyze({
12331
12377
  sessionId: req.session_id,
12332
12378
  promptSession: req.prompt_session,
@@ -12342,8 +12388,9 @@ async function analyzeRoute(c) {
12342
12388
  })),
12343
12389
  sessionHistory: (req.session_history || []).map((s) => ({
12344
12390
  sessionId: s.session_id,
12345
- // 来源 agent(AgentGate 逐会话带上,用于链路径取证展示;不参与链匹配)
12391
+ // 来源 agent/实例(AgentGate 逐会话带上,用于链路径取证/展示脱敏;不参与链匹配)
12346
12392
  ...s.agent_id ? { agentId: s.agent_id } : {},
12393
+ ...s.instance_id ? { instanceId: s.instance_id } : {},
12347
12394
  actionHistory: (s.action_history || []).map((h) => ({
12348
12395
  actionType: h.action_type,
12349
12396
  actionDetail: h.action_detail,
@@ -12367,11 +12414,13 @@ async function analyzeRoute(c) {
12367
12414
  })),
12368
12415
  aNext: {
12369
12416
  actionType: req.a_next.action_type,
12370
- actionDetail: req.a_next.action_detail
12417
+ actionDetail: req.a_next.action_detail,
12418
+ instanceId
12371
12419
  },
12372
12420
  reason: req.reason,
12373
12421
  osType,
12374
12422
  cwd: req.cwd,
12423
+ instanceId,
12375
12424
  // agent_id:AgentGate V1 normalizer 历史上把 agent_type 塞 metadata,
12376
12425
  // 顶层为空时兜底(OpenDesk 的 agent-moss 需 agent_id 加载专属规则)。
12377
12426
  agentId,
@@ -12407,8 +12456,9 @@ async function analyzeRoute(c) {
12407
12456
  { actionType: req.a_next.action_type, actionDetail: req.a_next.action_detail },
12408
12457
  req.session_id,
12409
12458
  Boolean(meta.is_error),
12410
- agentId
12459
+ agentId,
12411
12460
  // 来源:真实 agent(桶 key 可能是 __system__)
12461
+ instanceId
12412
12462
  );
12413
12463
  const judgment = incMatchedToDeny(inc);
12414
12464
  if (judgment) {
@@ -12429,8 +12479,8 @@ async function analyzeRoute(c) {
12429
12479
  confidence: 90,
12430
12480
  analysis_duration_ms: Math.round((performance.now() - t0) * 10) / 10,
12431
12481
  // 跨会话节点脱敏(时间线按 agent_id 共享,原样返回等于泄露别人的命令原文)
12432
- violation_chain: redactChain(judgment.violation_chain, req.session_id),
12433
- violation_graph: redactGraph(judgment.violation_graph, req.session_id)
12482
+ violation_chain: redactChain(judgment.violation_chain, instanceId, req.session_id),
12483
+ violation_graph: redactGraph(judgment.violation_graph, instanceId, req.session_id)
12434
12484
  })
12435
12485
  );
12436
12486
  }
@@ -12452,7 +12502,7 @@ async function analyzeRoute(c) {
12452
12502
  confidence: result.confidence,
12453
12503
  analysis_duration_ms: Math.round(durationMs * 10) / 10,
12454
12504
  violation_chain: result.violation_chain ?? [],
12455
- violation_graph: redactGraph(result.violation_graph, req.session_id)
12505
+ violation_graph: redactGraph(result.violation_graph, instanceId, req.session_id)
12456
12506
  })
12457
12507
  );
12458
12508
  } catch (err) {
@@ -81,6 +81,7 @@ interface AnalysisInput {
81
81
  * 由调用方(含未来 agentgate 非侵入式采集)提供。 */
82
82
  sessionHistory?: {
83
83
  sessionId?: string;
84
+ instanceId?: string;
84
85
  actionHistory: {
85
86
  actionType: string;
86
87
  actionDetail: string;
@@ -90,12 +91,15 @@ interface AnalysisInput {
90
91
  aNext: {
91
92
  actionType: string;
92
93
  actionDetail: string;
94
+ instanceId?: string;
93
95
  };
94
96
  reason: string;
95
97
  osType: string;
96
98
  cwd: string;
97
99
  /** 调用方 agent 标识(如 'xiaoo' / 'opencode' / 'opendesk')。空 = 通用模式。 */
98
100
  agentId: string;
101
+ /** 调用方实例标识(安装级)。仅用于展示层脱敏:同实例节点不隐藏。 */
102
+ instanceId?: string;
99
103
  /** 调用方场景标识(如 'bank'),用于加载场景定制规则(客户沙箱的目录访问边界/禁 ssh 等)。
100
104
  * 空时兜底环境变量 AGENT_MOSS_SCENARIO(部署级,客户沙箱设一次,所有请求生效)。 */
101
105
  scenarioId?: string;
@@ -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, agentId = "") {
8372
+ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "", instanceId = "") {
8373
8373
  const { integrity, isLowSource } = markIntegrity(actionDetail);
8374
8374
  return {
8375
8375
  sessionId,
@@ -8378,13 +8378,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId =
8378
8378
  actionDetail,
8379
8379
  stage: markStage(actionDetail),
8380
8380
  agentId: agentId || void 0,
8381
+ instanceId: instanceId || void 0,
8381
8382
  resources: extractResources(actionDetail),
8382
8383
  integrity,
8383
8384
  isLowSource,
8384
8385
  timestamp: timestamp || void 0
8385
8386
  };
8386
8387
  }
8387
- function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
8388
+ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "", instanceId = "") {
8388
8389
  const nodes = [];
8389
8390
  const edges = [];
8390
8391
  const stageFlags = /* @__PURE__ */ new Set();
@@ -8395,7 +8396,8 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8395
8396
  actionType: String(a.actionType || ""),
8396
8397
  actionDetail: ad,
8397
8398
  calledAt: a.calledAt || void 0,
8398
- agentId: a.agentId || agentId || void 0
8399
+ agentId: a.agentId || agentId || void 0,
8400
+ instanceId: a.instanceId || instanceId || void 0
8399
8401
  });
8400
8402
  }
8401
8403
  if (aNext) {
@@ -8403,11 +8405,12 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8403
8405
  actionType: String(aNext.actionType || ""),
8404
8406
  actionDetail: String(aNext.actionDetail || ""),
8405
8407
  calledAt: aNext.calledAt || void 0,
8406
- agentId: aNext.agentId || agentId || void 0
8408
+ agentId: aNext.agentId || agentId || void 0,
8409
+ instanceId: aNext.instanceId || instanceId || void 0
8407
8410
  });
8408
8411
  }
8409
8412
  details.forEach((d, seq) => {
8410
- const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
8413
+ const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "", d.instanceId || "");
8411
8414
  nodes.push(node);
8412
8415
  if (node.stage) stageFlags.add(node.stage);
8413
8416
  });
@@ -8419,12 +8422,18 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8419
8422
  function buildMultiSessionGraph(sessions, aNext) {
8420
8423
  const mg = { sessions: [], crossEdges: [] };
8421
8424
  if (!sessions || sessions.length === 0) {
8422
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
8425
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext?.instanceId || ""));
8423
8426
  return mg;
8424
8427
  }
8425
8428
  for (const s of sessions) {
8426
8429
  const sid = String(s.sessionId || "s");
8427
- mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
8430
+ mg.sessions.push(buildSessionGraph(
8431
+ s.actionHistory || [],
8432
+ void 0,
8433
+ sid,
8434
+ s.agentId || "",
8435
+ s.instanceId || ""
8436
+ ));
8428
8437
  }
8429
8438
  if (aNext) {
8430
8439
  const last = mg.sessions[mg.sessions.length - 1];
@@ -8435,13 +8444,14 @@ function buildMultiSessionGraph(sessions, aNext) {
8435
8444
  String(aNext.actionType || ""),
8436
8445
  String(aNext.actionDetail || ""),
8437
8446
  aNext.calledAt || void 0,
8438
- aNext.agentId || ""
8447
+ aNext.agentId || "",
8448
+ aNext.instanceId || ""
8439
8449
  ));
8440
8450
  if (last.nodes.length > 1) {
8441
8451
  last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
8442
8452
  }
8443
8453
  } else {
8444
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
8454
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext.instanceId || ""));
8445
8455
  }
8446
8456
  }
8447
8457
  addCrossDataEdges(mg);
@@ -8495,7 +8505,8 @@ function graphFromPath(nodes, path5, edgeType = "next", propertyMeta, roles, wit
8495
8505
  seq: item.seq,
8496
8506
  stage: n ? n.stage : "",
8497
8507
  action_detail: n ? n.actionDetail : item.detail,
8498
- resources: n ? [...n.resources].sort() : []
8508
+ resources: n ? [...n.resources].sort() : [],
8509
+ instance_id: n ? n.instanceId || "" : ""
8499
8510
  });
8500
8511
  if (gNodes.length > 1) {
8501
8512
  gEdges.push({ from: gNodes.length - 2, to: gNodes.length - 1, type: edgeType });
@@ -8666,7 +8677,8 @@ function checkSensitiveDataFlow(graph) {
8666
8677
  stage: n.stage,
8667
8678
  action_detail: n.actionDetail,
8668
8679
  resources: [...n.resources].sort(),
8669
- role
8680
+ role,
8681
+ instance_id: n.instanceId || ""
8670
8682
  });
8671
8683
  if (k > 0) {
8672
8684
  const prev = chain[k - 1];
@@ -9434,12 +9446,21 @@ async function runAnalysis(input) {
9434
9446
  formalSessions.push({
9435
9447
  sessionId: s.sessionId || "s",
9436
9448
  ...s.agentId ? { agentId: s.agentId } : {},
9449
+ ...s.instanceId ? { instanceId: s.instanceId } : {},
9437
9450
  actionHistory: s.actionHistory || []
9438
9451
  });
9439
9452
  }
9440
9453
  }
9441
- formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
9442
- const formalResult = formalEngine.verify(formalSessions, input.aNext);
9454
+ formalSessions.push({
9455
+ sessionId: "current",
9456
+ agentId: input.agentId,
9457
+ instanceId: input.instanceId || "",
9458
+ actionHistory: input.actionHistory
9459
+ });
9460
+ const formalResult = formalEngine.verify(formalSessions, {
9461
+ ...input.aNext,
9462
+ instanceId: input.instanceId || ""
9463
+ });
9443
9464
  if (!formalResult.verified) {
9444
9465
  const v = formalResult.violations[0];
9445
9466
  if (isFormalObserveMode()) {
package/dist/server.js CHANGED
@@ -1092,31 +1092,42 @@ function hardenExistingPaths() {
1092
1092
  function chainDetailMode() {
1093
1093
  return (env("AGENT_MOSS_CHAIN_DETAIL", "redacted") || "redacted").toLowerCase();
1094
1094
  }
1095
- function redactChain(chain, currentSessionId) {
1095
+ function redactChain(chain, currentInstanceId = "", currentSessionId = "") {
1096
1096
  if (!chain || chain.length === 0) return [];
1097
1097
  if (chainDetailMode() === "full") return [...chain];
1098
1098
  return chain.map((step) => {
1099
1099
  if (Array.isArray(step) && step.length >= 3) {
1100
1100
  const [sid, seq, , ts] = step;
1101
- if (String(sid) === String(currentSessionId)) return [...step];
1101
+ const inst = step.length > 5 ? String(step[5] ?? "") : "";
1102
+ const sameInstance = !!(inst && currentInstanceId && inst === String(currentInstanceId));
1103
+ const sameSessionFallback = !inst && !!currentSessionId && String(sid) === String(currentSessionId);
1104
+ if (sameInstance || sameSessionFallback) return [...step];
1102
1105
  return ["<other-session>", seq, "<\u5DF2\u9690\u85CF>", ts ?? ""];
1103
1106
  }
1104
1107
  return step;
1105
1108
  });
1106
1109
  }
1107
- function redactGraph(graph, currentSessionId) {
1110
+ function redactGraph(graph, currentInstanceId = "", currentSessionId = "") {
1108
1111
  if (!graph) return null;
1109
1112
  if (chainDetailMode() === "full") return graph;
1110
1113
  const nodes = (graph.nodes || []).map((n) => {
1111
1114
  const m = { ...n };
1112
- if (String(m.session_id ?? "") !== String(currentSessionId)) {
1115
+ const inst = String(m.instance_id ?? "") || "";
1116
+ const sid = String(m.session_id ?? "") || "";
1117
+ const sameInstance = !!(inst && currentInstanceId && inst === String(currentInstanceId));
1118
+ const sameSessionFallback = !inst && !!currentSessionId && sid === String(currentSessionId);
1119
+ if (!(sameInstance || sameSessionFallback)) {
1113
1120
  m.session_id = "<other-session>";
1114
1121
  m.action_detail = "<\u5DF2\u9690\u85CF>";
1115
1122
  m.resources = [];
1116
1123
  }
1117
1124
  return m;
1118
1125
  });
1119
- return { nodes, edges: graph.edges || [] };
1126
+ const out = { nodes, edges: graph.edges || [] };
1127
+ for (const key of ["property_id", "property_short", "property_name", "property_expression"]) {
1128
+ if (graph[key] !== void 0) out[key] = graph[key];
1129
+ }
1130
+ return out;
1120
1131
  }
1121
1132
  function sessionSweepThreshold() {
1122
1133
  return envInt("AGENT_MOSS_SESSION_SWEEP_THRESHOLD", 50);
@@ -8884,7 +8895,7 @@ function markIntegrity(actionDetail) {
8884
8895
  }
8885
8896
  return { integrity: "medium", isLowSource: false };
8886
8897
  }
8887
- function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "") {
8898
+ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId = "", instanceId = "") {
8888
8899
  const { integrity, isLowSource } = markIntegrity(actionDetail);
8889
8900
  return {
8890
8901
  sessionId,
@@ -8893,13 +8904,14 @@ function initNode(sessionId, seq, actionType, actionDetail, timestamp, agentId =
8893
8904
  actionDetail,
8894
8905
  stage: markStage(actionDetail),
8895
8906
  agentId: agentId || void 0,
8907
+ instanceId: instanceId || void 0,
8896
8908
  resources: extractResources(actionDetail),
8897
8909
  integrity,
8898
8910
  isLowSource,
8899
8911
  timestamp: timestamp || void 0
8900
8912
  };
8901
8913
  }
8902
- function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "") {
8914
+ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId = "", instanceId = "") {
8903
8915
  const nodes = [];
8904
8916
  const edges = [];
8905
8917
  const stageFlags = /* @__PURE__ */ new Set();
@@ -8910,7 +8922,8 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8910
8922
  actionType: String(a.actionType || ""),
8911
8923
  actionDetail: ad,
8912
8924
  calledAt: a.calledAt || void 0,
8913
- agentId: a.agentId || agentId || void 0
8925
+ agentId: a.agentId || agentId || void 0,
8926
+ instanceId: a.instanceId || instanceId || void 0
8914
8927
  });
8915
8928
  }
8916
8929
  if (aNext) {
@@ -8918,11 +8931,12 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8918
8931
  actionType: String(aNext.actionType || ""),
8919
8932
  actionDetail: String(aNext.actionDetail || ""),
8920
8933
  calledAt: aNext.calledAt || void 0,
8921
- agentId: aNext.agentId || agentId || void 0
8934
+ agentId: aNext.agentId || agentId || void 0,
8935
+ instanceId: aNext.instanceId || instanceId || void 0
8922
8936
  });
8923
8937
  }
8924
8938
  details.forEach((d, seq) => {
8925
- const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "");
8939
+ const node = initNode(sessionId, seq, d.actionType, d.actionDetail, d.calledAt, d.agentId || "", d.instanceId || "");
8926
8940
  nodes.push(node);
8927
8941
  if (node.stage) stageFlags.add(node.stage);
8928
8942
  });
@@ -8934,12 +8948,18 @@ function buildSessionGraph(actionHistory, aNext, sessionId = "current", agentId
8934
8948
  function buildMultiSessionGraph(sessions, aNext) {
8935
8949
  const mg = { sessions: [], crossEdges: [] };
8936
8950
  if (!sessions || sessions.length === 0) {
8937
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
8951
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext?.instanceId || ""));
8938
8952
  return mg;
8939
8953
  }
8940
8954
  for (const s of sessions) {
8941
8955
  const sid = String(s.sessionId || "s");
8942
- mg.sessions.push(buildSessionGraph(s.actionHistory || [], void 0, sid, s.agentId || ""));
8956
+ mg.sessions.push(buildSessionGraph(
8957
+ s.actionHistory || [],
8958
+ void 0,
8959
+ sid,
8960
+ s.agentId || "",
8961
+ s.instanceId || ""
8962
+ ));
8943
8963
  }
8944
8964
  if (aNext) {
8945
8965
  const last = mg.sessions[mg.sessions.length - 1];
@@ -8950,13 +8970,14 @@ function buildMultiSessionGraph(sessions, aNext) {
8950
8970
  String(aNext.actionType || ""),
8951
8971
  String(aNext.actionDetail || ""),
8952
8972
  aNext.calledAt || void 0,
8953
- aNext.agentId || ""
8973
+ aNext.agentId || "",
8974
+ aNext.instanceId || ""
8954
8975
  ));
8955
8976
  if (last.nodes.length > 1) {
8956
8977
  last.edges.push({ src: last.nodes.length - 2, dst: last.nodes.length - 1, kind: "next" });
8957
8978
  }
8958
8979
  } else {
8959
- mg.sessions.push(buildSessionGraph([], aNext, "current"));
8980
+ mg.sessions.push(buildSessionGraph([], aNext, "current", "", aNext.instanceId || ""));
8960
8981
  }
8961
8982
  }
8962
8983
  addCrossDataEdges(mg);
@@ -9020,7 +9041,8 @@ function graphFromPath(nodes, path6, edgeType = "next", propertyMeta, roles, wit
9020
9041
  seq: item.seq,
9021
9042
  stage: n ? n.stage : "",
9022
9043
  action_detail: n ? n.actionDetail : item.detail,
9023
- resources: n ? [...n.resources].sort() : []
9044
+ resources: n ? [...n.resources].sort() : [],
9045
+ instance_id: n ? n.instanceId || "" : ""
9024
9046
  });
9025
9047
  if (gNodes.length > 1) {
9026
9048
  gEdges.push({ from: gNodes.length - 2, to: gNodes.length - 1, type: edgeType });
@@ -9188,7 +9210,8 @@ function checkSensitiveDataFlow(graph) {
9188
9210
  stage: n.stage,
9189
9211
  action_detail: n.actionDetail,
9190
9212
  resources: [...n.resources].sort(),
9191
- role
9213
+ role,
9214
+ instance_id: n.instanceId || ""
9192
9215
  });
9193
9216
  if (k > 0) {
9194
9217
  const prev = chain[k - 1];
@@ -9831,7 +9854,7 @@ var init_stateful = __esm({
9831
9854
  for (const s of sessions || []) {
9832
9855
  const sid = String(s.sessionId || "s");
9833
9856
  for (const a of s.actionHistory || []) {
9834
- const node = this.appendNode(a, sid);
9857
+ const node = this.appendNode(a, sid, false, s.agentId || "", s.instanceId || "");
9835
9858
  if (!node) {
9836
9859
  continue;
9837
9860
  }
@@ -9845,8 +9868,8 @@ var init_stateful = __esm({
9845
9868
  }
9846
9869
  /** 增量推进:把当前动作追加到时间线 → 链指针推进 → 判定。 */
9847
9870
  advance(args) {
9848
- const { aNext, sessionId = "current", isError = false, agentId = "" } = args;
9849
- const node = this.appendNode(aNext, sessionId, isError, agentId);
9871
+ const { aNext, sessionId = "current", isError = false, agentId = "", instanceId = "" } = args;
9872
+ const node = this.appendNode(aNext, sessionId, isError, agentId, instanceId);
9850
9873
  if (!node) {
9851
9874
  return { seq: this.seqNext, node: null, matched: null, pendingPrefixes: this.pendingPrefixes, exfil: [], shouldBlock: false };
9852
9875
  }
@@ -9866,7 +9889,7 @@ var init_stateful = __esm({
9866
9889
  }
9867
9890
  };
9868
9891
  }
9869
- appendNode(action, sessionId, isError = false, agentId = "") {
9892
+ appendNode(action, sessionId, isError = false, agentId = "", instanceId = "") {
9870
9893
  const ad = String(action.actionDetail || "");
9871
9894
  const at = String(action.actionType || "");
9872
9895
  if (!ad) return null;
@@ -9884,6 +9907,7 @@ var init_stateful = __esm({
9884
9907
  instances: extractInstances(ad, stage),
9885
9908
  isError,
9886
9909
  agentId: String(action.agentId || agentId || ""),
9910
+ instanceId: String(action.instanceId || instanceId || ""),
9887
9911
  lifecycle: lifecycleFor(ad, stage, isError),
9888
9912
  timestamp: typeof action.calledAt === "string" ? action.calledAt : _StatefulChainTracker.now()
9889
9913
  };
@@ -10027,7 +10051,8 @@ var init_stateful = __esm({
10027
10051
  seq: n.seq,
10028
10052
  stage: n.stage,
10029
10053
  timestamp: n.timestamp,
10030
- agentId: n.agentId
10054
+ agentId: n.agentId,
10055
+ instanceId: n.instanceId
10031
10056
  });
10032
10057
  const idx = stages.indexOf(n.stage);
10033
10058
  if (idx + 1 < stages.length) {
@@ -10050,7 +10075,8 @@ var init_stateful = __esm({
10050
10075
  stage: p.stage,
10051
10076
  action_detail: n ? n.actionDetail : "",
10052
10077
  resources: n ? [...n.resources].sort() : [],
10053
- role: stages[i] || ""
10078
+ role: stages[i] || "",
10079
+ instance_id: p.instanceId || ""
10054
10080
  };
10055
10081
  });
10056
10082
  const gEdges = [];
@@ -10118,7 +10144,7 @@ var init_stateful = __esm({
10118
10144
  risk_level: "critical",
10119
10145
  path: chain.map((j) => {
10120
10146
  const n = this.nodes_[j];
10121
- return [n.sessionId, n.seq, n.actionDetail.slice(0, 60), n.timestamp];
10147
+ return [n.sessionId, n.seq, n.actionDetail.slice(0, 60), n.timestamp, null, n.instanceId];
10122
10148
  }),
10123
10149
  graph: this.taintGraph(chain)
10124
10150
  }];
@@ -10150,7 +10176,8 @@ var init_stateful = __esm({
10150
10176
  stage: n.stage,
10151
10177
  action_detail: n.actionDetail,
10152
10178
  resources: [...n.resources].sort(),
10153
- role
10179
+ role,
10180
+ instance_id: n.instanceId
10154
10181
  });
10155
10182
  if (k > 0) {
10156
10183
  const prev = chain[k - 1];
@@ -10222,6 +10249,8 @@ var init_stateful = __esm({
10222
10249
  seq: Number(raw.seq || 0),
10223
10250
  sessionId: String(raw.sessionId || ""),
10224
10251
  agentId: String(raw.agentId || ""),
10252
+ instanceId: String(raw.instanceId || ""),
10253
+ // 旧快照无此字段 → 空
10225
10254
  actionType: String(raw.actionType || ""),
10226
10255
  actionDetail: String(raw.actionDetail || ""),
10227
10256
  stage: String(raw.stage || ""),
@@ -10366,9 +10395,9 @@ var init_chain_state = __esm({
10366
10395
  delete this.data[agentId];
10367
10396
  this._scheduleWrite();
10368
10397
  }
10369
- applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "") {
10398
+ applyAction(agentId, aNext, sessionId, isError = false, sourceAgent = "", instanceId = "") {
10370
10399
  const t = this.load(agentId) || new StatefulChainTracker(agentId);
10371
- const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent });
10400
+ const r = t.advance({ aNext, sessionId, isError, agentId: sourceAgent, instanceId });
10372
10401
  this.save(t);
10373
10402
  return r;
10374
10403
  }
@@ -10686,12 +10715,21 @@ async function runAnalysis(input) {
10686
10715
  formalSessions.push({
10687
10716
  sessionId: s.sessionId || "s",
10688
10717
  ...s.agentId ? { agentId: s.agentId } : {},
10718
+ ...s.instanceId ? { instanceId: s.instanceId } : {},
10689
10719
  actionHistory: s.actionHistory || []
10690
10720
  });
10691
10721
  }
10692
10722
  }
10693
- formalSessions.push({ sessionId: "current", agentId: input.agentId, actionHistory: input.actionHistory });
10694
- const formalResult = formalEngine.verify(formalSessions, input.aNext);
10723
+ formalSessions.push({
10724
+ sessionId: "current",
10725
+ agentId: input.agentId,
10726
+ instanceId: input.instanceId || "",
10727
+ actionHistory: input.actionHistory
10728
+ });
10729
+ const formalResult = formalEngine.verify(formalSessions, {
10730
+ ...input.aNext,
10731
+ instanceId: input.instanceId || ""
10732
+ });
10695
10733
  if (!formalResult.verified) {
10696
10734
  const v = formalResult.violations[0];
10697
10735
  if (isFormalObserveMode()) {
@@ -11062,6 +11100,8 @@ var AnalyzeRequestSchema = z.object({
11062
11100
  session_id: z.string(),
11063
11101
  /** 来源 agent(AgentGate 逐会话带上):记录在链路径里供告警/取证,不参与链匹配。 */
11064
11102
  agent_id: z.string().optional(),
11103
+ /** 来源实例:仅用于展示层脱敏(同实例不隐藏),不参与链匹配。 */
11104
+ instance_id: z.string().optional(),
11065
11105
  action_history: z.array(ActionItemSchema).default([])
11066
11106
  })).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)."),
11067
11107
  a_next: ActionItemSchema.describe("Next action to be executed"),
@@ -11069,6 +11109,7 @@ var AnalyzeRequestSchema = z.object({
11069
11109
  os_type: z.string().default("").describe("OS type: 'linux', 'windows', or empty for auto-detect"),
11070
11110
  cwd: z.string().default("").describe("Current working directory"),
11071
11111
  agent_id: z.string().default("").describe("Caller agent identifier, e.g. 'xiaoo' / 'opencode' / 'opendesk'. Empty = generic mode (no agent-specific rules)."),
11112
+ instance_id: z.string().default("").describe("Agent installation/instance identifier. Used only for display-layer redaction: nodes from the same instance are returned unredacted. Does not affect detection."),
11072
11113
  metadata: z.record(z.unknown()).optional().describe("Extended metadata")
11073
11114
  });
11074
11115
  var AnalyzeResponseSchema = z.object({
@@ -11106,7 +11147,9 @@ var AnalyzeResponseSchema = z.object({
11106
11147
  // 节点在性质中的角色:source/carrier/sink(P2)或阶段名(P1)
11107
11148
  role: z.string().optional(),
11108
11149
  // 是否为违例见证节点(当前动作补全链 / 触发外传)
11109
- witness: z.boolean().optional()
11150
+ witness: z.boolean().optional(),
11151
+ // 来源实例(仅展示层脱敏:同实例不隐藏)
11152
+ instance_id: z.string().optional()
11110
11153
  })
11111
11154
  ),
11112
11155
  edges: z.array(
@@ -11998,6 +12041,9 @@ async function analyzeRoute(c) {
11998
12041
  `[AgentMoss] \u26A0\uFE0F \u8DE8\u4F1A\u8BDD\u6279\u91CF\u8BBF\u95EE: key=${_sweepKey} \u7A97\u53E3\u5185 ${_sweepN} \u4E2A\u4E0D\u540C session\uFF08\u9608\u503C ${sessionSweepThreshold()}\uFF09`
11999
12042
  );
12000
12043
  }
12044
+ const instanceId = String(
12045
+ req.instance_id || req.metadata?.instance_id || ""
12046
+ );
12001
12047
  const result = await analyze({
12002
12048
  sessionId: req.session_id,
12003
12049
  promptSession: req.prompt_session,
@@ -12013,8 +12059,9 @@ async function analyzeRoute(c) {
12013
12059
  })),
12014
12060
  sessionHistory: (req.session_history || []).map((s) => ({
12015
12061
  sessionId: s.session_id,
12016
- // 来源 agent(AgentGate 逐会话带上,用于链路径取证展示;不参与链匹配)
12062
+ // 来源 agent/实例(AgentGate 逐会话带上,用于链路径取证/展示脱敏;不参与链匹配)
12017
12063
  ...s.agent_id ? { agentId: s.agent_id } : {},
12064
+ ...s.instance_id ? { instanceId: s.instance_id } : {},
12018
12065
  actionHistory: (s.action_history || []).map((h) => ({
12019
12066
  actionType: h.action_type,
12020
12067
  actionDetail: h.action_detail,
@@ -12038,11 +12085,13 @@ async function analyzeRoute(c) {
12038
12085
  })),
12039
12086
  aNext: {
12040
12087
  actionType: req.a_next.action_type,
12041
- actionDetail: req.a_next.action_detail
12088
+ actionDetail: req.a_next.action_detail,
12089
+ instanceId
12042
12090
  },
12043
12091
  reason: req.reason,
12044
12092
  osType,
12045
12093
  cwd: req.cwd,
12094
+ instanceId,
12046
12095
  // agent_id:AgentGate V1 normalizer 历史上把 agent_type 塞 metadata,
12047
12096
  // 顶层为空时兜底(OpenDesk 的 agent-moss 需 agent_id 加载专属规则)。
12048
12097
  agentId,
@@ -12078,8 +12127,9 @@ async function analyzeRoute(c) {
12078
12127
  { actionType: req.a_next.action_type, actionDetail: req.a_next.action_detail },
12079
12128
  req.session_id,
12080
12129
  Boolean(meta.is_error),
12081
- agentId
12130
+ agentId,
12082
12131
  // 来源:真实 agent(桶 key 可能是 __system__)
12132
+ instanceId
12083
12133
  );
12084
12134
  const judgment = incMatchedToDeny(inc);
12085
12135
  if (judgment) {
@@ -12100,8 +12150,8 @@ async function analyzeRoute(c) {
12100
12150
  confidence: 90,
12101
12151
  analysis_duration_ms: Math.round((performance.now() - t0) * 10) / 10,
12102
12152
  // 跨会话节点脱敏(时间线按 agent_id 共享,原样返回等于泄露别人的命令原文)
12103
- violation_chain: redactChain(judgment.violation_chain, req.session_id),
12104
- violation_graph: redactGraph(judgment.violation_graph, req.session_id)
12153
+ violation_chain: redactChain(judgment.violation_chain, instanceId, req.session_id),
12154
+ violation_graph: redactGraph(judgment.violation_graph, instanceId, req.session_id)
12105
12155
  })
12106
12156
  );
12107
12157
  }
@@ -12123,7 +12173,7 @@ async function analyzeRoute(c) {
12123
12173
  confidence: result.confidence,
12124
12174
  analysis_duration_ms: Math.round(durationMs * 10) / 10,
12125
12175
  violation_chain: result.violation_chain ?? [],
12126
- violation_graph: redactGraph(result.violation_graph, req.session_id)
12176
+ violation_graph: redactGraph(result.violation_graph, instanceId, req.session_id)
12127
12177
  })
12128
12178
  );
12129
12179
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenhkl/agent-moss",
3
- "version": "0.17.8",
3
+ "version": "0.17.10",
4
4
  "description": "Multi-layer security analysis engine for AI agents (TypeScript)",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",