@sechroom/cli 2026.7.4 → 2026.7.6
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/index.js +49 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1545,6 +1545,7 @@ function registerChannel(program2) {
|
|
|
1545
1545
|
const filter = readFilter(opts);
|
|
1546
1546
|
const sub = await ensureSubscription(cfg, opts.name, filter);
|
|
1547
1547
|
const conn = await openConnection(cfg, (payload) => {
|
|
1548
|
+
if (!shouldDeliver(payload, filter)) return;
|
|
1548
1549
|
process.stdout.write(
|
|
1549
1550
|
(typeof payload === "string" ? payload : JSON.stringify(payload)) + "\n"
|
|
1550
1551
|
);
|
|
@@ -1586,6 +1587,7 @@ function registerChannel(program2) {
|
|
|
1586
1587
|
await mcp.connect(new StdioServerTransport());
|
|
1587
1588
|
await ensureSubscription(cfg, opts.name, filter);
|
|
1588
1589
|
const conn = await openConnection(cfg, (payload) => {
|
|
1590
|
+
if (!shouldDeliver(payload, filter)) return;
|
|
1589
1591
|
const { content, meta } = summarizeEvent(payload);
|
|
1590
1592
|
void mcp.notification({
|
|
1591
1593
|
method: "notifications/claude/channel",
|
|
@@ -1605,7 +1607,10 @@ function registerChannel(program2) {
|
|
|
1605
1607
|
});
|
|
1606
1608
|
channel.command("install").description(
|
|
1607
1609
|
"Wire `sechroom channel mcp` into the project .mcp.json as a Claude Code channel MCP server (idempotent)"
|
|
1608
|
-
).option(
|
|
1610
|
+
).option(
|
|
1611
|
+
"--workspace <wsp...>",
|
|
1612
|
+
"Restrict dispatches to these workspace id(s)"
|
|
1613
|
+
).option(
|
|
1609
1614
|
"--tag <tag...>",
|
|
1610
1615
|
"Tag(s) a dispatch must carry to match (repeatable). Default targets WLP task dispatches.",
|
|
1611
1616
|
["kind:task"]
|
|
@@ -1726,20 +1731,58 @@ function holdOpen(conn) {
|
|
|
1726
1731
|
process.on("SIGTERM", stop);
|
|
1727
1732
|
});
|
|
1728
1733
|
}
|
|
1729
|
-
function
|
|
1734
|
+
function parseEvent(payload) {
|
|
1730
1735
|
let data = payload;
|
|
1731
1736
|
if (typeof payload === "string") {
|
|
1732
1737
|
try {
|
|
1733
1738
|
data = JSON.parse(payload);
|
|
1734
1739
|
} catch {
|
|
1735
|
-
return {
|
|
1740
|
+
return { eventType: "", memoryId: "", workspaceId: "", tags: void 0 };
|
|
1736
1741
|
}
|
|
1737
1742
|
}
|
|
1738
1743
|
const obj = data ?? {};
|
|
1739
1744
|
const inner = obj.data ?? obj;
|
|
1740
|
-
const
|
|
1741
|
-
|
|
1742
|
-
|
|
1745
|
+
const rawTags = inner.tags ?? inner.Tags;
|
|
1746
|
+
return {
|
|
1747
|
+
eventType: str(inner.eventType ?? inner.EventType ?? obj.type) || "substrate.event",
|
|
1748
|
+
memoryId: str(inner.memoryId ?? inner.MemoryId),
|
|
1749
|
+
workspaceId: str(inner.workspaceId ?? inner.WorkspaceId),
|
|
1750
|
+
tags: Array.isArray(rawTags) ? rawTags.filter((t) => typeof t === "string") : void 0
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
function shouldDeliver(payload, filter) {
|
|
1754
|
+
const { workspaceId, tags } = parseEvent(payload);
|
|
1755
|
+
if (filter.workspaceScope.length > 0 && (!workspaceId || !filter.workspaceScope.includes(workspaceId)))
|
|
1756
|
+
return false;
|
|
1757
|
+
if (filter.tags.length > 0) {
|
|
1758
|
+
if (!tags) return false;
|
|
1759
|
+
return facetedTagMatch(tags, filter.tags);
|
|
1760
|
+
}
|
|
1761
|
+
return true;
|
|
1762
|
+
}
|
|
1763
|
+
function facetedTagMatch(eventTags, filterTags) {
|
|
1764
|
+
const have = new Set(eventTags);
|
|
1765
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1766
|
+
for (const f of filterTags) {
|
|
1767
|
+
const ns = f.endsWith(":*") ? f.slice(0, -2) : namespaceOf(f);
|
|
1768
|
+
const group = groups.get(ns) ?? [];
|
|
1769
|
+
group.push(f);
|
|
1770
|
+
groups.set(ns, group);
|
|
1771
|
+
}
|
|
1772
|
+
for (const [ns, group] of groups) {
|
|
1773
|
+
const ok2 = group.some(
|
|
1774
|
+
(f) => f.endsWith(":*") ? eventTags.some((t) => namespaceOf(t) === ns) : have.has(f)
|
|
1775
|
+
);
|
|
1776
|
+
if (!ok2) return false;
|
|
1777
|
+
}
|
|
1778
|
+
return true;
|
|
1779
|
+
}
|
|
1780
|
+
function namespaceOf(tag) {
|
|
1781
|
+
const i = tag.indexOf(":");
|
|
1782
|
+
return i >= 0 ? tag.slice(0, i) : tag;
|
|
1783
|
+
}
|
|
1784
|
+
function summarizeEvent(payload) {
|
|
1785
|
+
const { eventType, memoryId, workspaceId } = parseEvent(payload);
|
|
1743
1786
|
const content = memoryId ? `${eventType}: ${memoryId}${workspaceId ? ` (workspace ${workspaceId})` : ""}` : typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
1744
1787
|
const meta = {};
|
|
1745
1788
|
if (eventType) meta.event_type = eventType;
|
package/package.json
CHANGED