agenthub-multiagent-mcp 1.75.0 → 1.76.1

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.
Files changed (112) hide show
  1. package/dist/client.d.ts +19 -1
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +31 -0
  4. package/dist/client.js.map +1 -1
  5. package/dist/commands/setup-shell.js +11 -11
  6. package/dist/currentCaptureSession.d.ts +31 -0
  7. package/dist/currentCaptureSession.d.ts.map +1 -0
  8. package/dist/currentCaptureSession.js +54 -0
  9. package/dist/currentCaptureSession.js.map +1 -0
  10. package/dist/currentCaptureSession.test.d.ts +2 -0
  11. package/dist/currentCaptureSession.test.d.ts.map +1 -0
  12. package/dist/currentCaptureSession.test.js +55 -0
  13. package/dist/currentCaptureSession.test.js.map +1 -0
  14. package/dist/employee.d.ts +11 -0
  15. package/dist/employee.d.ts.map +1 -1
  16. package/dist/employee.js +64 -1
  17. package/dist/employee.js.map +1 -1
  18. package/dist/employee.test.js +88 -1
  19. package/dist/employee.test.js.map +1 -1
  20. package/dist/goshtiChannel/client.d.ts +9 -0
  21. package/dist/goshtiChannel/client.d.ts.map +1 -0
  22. package/dist/goshtiChannel/client.js +63 -0
  23. package/dist/goshtiChannel/client.js.map +1 -0
  24. package/dist/goshtiChannel/config.d.ts +42 -0
  25. package/dist/goshtiChannel/config.d.ts.map +1 -0
  26. package/dist/goshtiChannel/config.js +129 -0
  27. package/dist/goshtiChannel/config.js.map +1 -0
  28. package/dist/goshtiChannel/config.test.d.ts +2 -0
  29. package/dist/goshtiChannel/config.test.d.ts.map +1 -0
  30. package/dist/goshtiChannel/config.test.js +73 -0
  31. package/dist/goshtiChannel/config.test.js.map +1 -0
  32. package/dist/goshtiChannel/core.d.ts +63 -0
  33. package/dist/goshtiChannel/core.d.ts.map +1 -0
  34. package/dist/goshtiChannel/core.js +237 -0
  35. package/dist/goshtiChannel/core.js.map +1 -0
  36. package/dist/goshtiChannel/core.test.d.ts +2 -0
  37. package/dist/goshtiChannel/core.test.d.ts.map +1 -0
  38. package/dist/goshtiChannel/core.test.js +250 -0
  39. package/dist/goshtiChannel/core.test.js.map +1 -0
  40. package/dist/goshtiChannel/credential.d.ts +29 -0
  41. package/dist/goshtiChannel/credential.d.ts.map +1 -0
  42. package/dist/goshtiChannel/credential.js +160 -0
  43. package/dist/goshtiChannel/credential.js.map +1 -0
  44. package/dist/goshtiChannel/credential.test.d.ts +2 -0
  45. package/dist/goshtiChannel/credential.test.d.ts.map +1 -0
  46. package/dist/goshtiChannel/credential.test.js +127 -0
  47. package/dist/goshtiChannel/credential.test.js.map +1 -0
  48. package/dist/goshtiChannel/e2e.test.d.ts +2 -0
  49. package/dist/goshtiChannel/e2e.test.d.ts.map +1 -0
  50. package/dist/goshtiChannel/e2e.test.js +163 -0
  51. package/dist/goshtiChannel/e2e.test.js.map +1 -0
  52. package/dist/goshtiChannel/policy.d.ts +154 -0
  53. package/dist/goshtiChannel/policy.d.ts.map +1 -0
  54. package/dist/goshtiChannel/policy.js +240 -0
  55. package/dist/goshtiChannel/policy.js.map +1 -0
  56. package/dist/goshtiChannel/policy.test.d.ts +2 -0
  57. package/dist/goshtiChannel/policy.test.d.ts.map +1 -0
  58. package/dist/goshtiChannel/policy.test.js +263 -0
  59. package/dist/goshtiChannel/policy.test.js.map +1 -0
  60. package/dist/goshtiChannel/setup.d.ts +15 -0
  61. package/dist/goshtiChannel/setup.d.ts.map +1 -0
  62. package/dist/goshtiChannel/setup.js +125 -0
  63. package/dist/goshtiChannel/setup.js.map +1 -0
  64. package/dist/goshtiChannel/setup.test.d.ts +2 -0
  65. package/dist/goshtiChannel/setup.test.d.ts.map +1 -0
  66. package/dist/goshtiChannel/setup.test.js +96 -0
  67. package/dist/goshtiChannel/setup.test.js.map +1 -0
  68. package/dist/goshtiChannel/stream.d.ts +39 -0
  69. package/dist/goshtiChannel/stream.d.ts.map +1 -0
  70. package/dist/goshtiChannel/stream.js +174 -0
  71. package/dist/goshtiChannel/stream.js.map +1 -0
  72. package/dist/goshtiChannel/stream.test.d.ts +2 -0
  73. package/dist/goshtiChannel/stream.test.d.ts.map +1 -0
  74. package/dist/goshtiChannel/stream.test.js +164 -0
  75. package/dist/goshtiChannel/stream.test.js.map +1 -0
  76. package/dist/goshtiChannel.d.ts +22 -0
  77. package/dist/goshtiChannel.d.ts.map +1 -0
  78. package/dist/goshtiChannel.js +193 -0
  79. package/dist/goshtiChannel.js.map +1 -0
  80. package/dist/state.d.ts +2 -0
  81. package/dist/state.d.ts.map +1 -1
  82. package/dist/state.js.map +1 -1
  83. package/dist/tools/brainWriteCheck.test.d.ts +10 -0
  84. package/dist/tools/brainWriteCheck.test.d.ts.map +1 -0
  85. package/dist/tools/brainWriteCheck.test.js +67 -0
  86. package/dist/tools/brainWriteCheck.test.js.map +1 -0
  87. package/dist/tools/employeeTraining.d.ts +46 -0
  88. package/dist/tools/employeeTraining.d.ts.map +1 -0
  89. package/dist/tools/employeeTraining.js +329 -0
  90. package/dist/tools/employeeTraining.js.map +1 -0
  91. package/dist/tools/employeeTraining.test.d.ts +7 -0
  92. package/dist/tools/employeeTraining.test.d.ts.map +1 -0
  93. package/dist/tools/employeeTraining.test.js +190 -0
  94. package/dist/tools/employeeTraining.test.js.map +1 -0
  95. package/dist/tools/index.d.ts.map +1 -1
  96. package/dist/tools/index.js +155 -5
  97. package/dist/tools/index.js.map +1 -1
  98. package/dist/tools/runs.d.ts +43 -0
  99. package/dist/tools/runs.d.ts.map +1 -0
  100. package/dist/tools/runs.js +280 -0
  101. package/dist/tools/runs.js.map +1 -0
  102. package/dist/tools/runs.test.d.ts +9 -0
  103. package/dist/tools/runs.test.d.ts.map +1 -0
  104. package/dist/tools/runs.test.js +114 -0
  105. package/dist/tools/runs.test.js.map +1 -0
  106. package/dist/tools/tools.test.js +82 -2
  107. package/dist/tools/tools.test.js.map +1 -1
  108. package/package.json +79 -78
  109. package/skills/catalog.json +104 -102
  110. package/skills/commands/close-session.md +2 -2
  111. package/skills/commands/start-session.md +2 -2
  112. package/skills/manifest.json +67 -65
@@ -0,0 +1,163 @@
1
+ // The real entry point, spawned the way Claude Code spawns it, against a local
2
+ // stand-in for Goshti (REST + WebSocket). Covers what the unit tests cannot:
3
+ // that a failure reaches the session as a channel notification rather than a
4
+ // silent idle server, and that a trigger posted in Goshti arrives and can be
5
+ // answered in its thread.
6
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
8
+ import { mkdtempSync, writeFileSync } from "node:fs";
9
+ import { createServer } from "node:http";
10
+ import { tmpdir } from "node:os";
11
+ import { join, resolve } from "node:path";
12
+ import { afterEach, describe, expect, it } from "vitest";
13
+ import { z } from "zod";
14
+ import { WebSocketServer } from "ws";
15
+ const ENTRY = resolve(__dirname, "..", "goshtiChannel.ts");
16
+ const TOKEN = "e2e-token-not-real";
17
+ const Note = z.object({
18
+ method: z.literal("notifications/claude/channel"),
19
+ params: z.object({ content: z.string(), meta: z.record(z.string(), z.string()) }),
20
+ });
21
+ const cleanups = [];
22
+ afterEach(async () => {
23
+ for (const c of cleanups.splice(0).reverse())
24
+ await c();
25
+ });
26
+ function home(config, credential = true) {
27
+ const d = mkdtempSync(join(tmpdir(), "goshti-e2e-"));
28
+ if (config)
29
+ writeFileSync(join(d, "config.json"), JSON.stringify(config));
30
+ if (credential && config) {
31
+ writeFileSync(join(d, "credentials.json"), JSON.stringify({ accounts: { [String(config.url)]: TOKEN } }), {
32
+ mode: 0o600,
33
+ });
34
+ }
35
+ return d;
36
+ }
37
+ async function start(dir) {
38
+ const notes = [];
39
+ const client = new Client({ name: "e2e", version: "0" }, { capabilities: {} });
40
+ client.setNotificationHandler(Note, async (n) => {
41
+ notes.push(n.params);
42
+ });
43
+ const transport = new StdioClientTransport({
44
+ command: process.execPath,
45
+ args: ["--import", "tsx", ENTRY],
46
+ env: { ...process.env, GOSHTI_CHANNEL_HOME: dir },
47
+ stderr: "pipe",
48
+ });
49
+ await client.connect(transport);
50
+ cleanups.push(() => client.close());
51
+ return { client, notes };
52
+ }
53
+ async function until(cond, ms = 15_000) {
54
+ const t = Date.now();
55
+ while (!cond()) {
56
+ if (Date.now() - t > ms)
57
+ throw new Error("timed out");
58
+ await new Promise((r) => setTimeout(r, 25));
59
+ }
60
+ }
61
+ async function goshti(opts = {}) {
62
+ const posts = [];
63
+ const http = createServer((req, res) => {
64
+ if (req.headers.authorization !== `Bearer ${TOKEN}` || opts.refuse) {
65
+ res.writeHead(401).end("{}");
66
+ return;
67
+ }
68
+ if (req.url === "/api/v4/users/me") {
69
+ res.end(JSON.stringify({ id: "me1", username: "sumit", is_bot: false }));
70
+ }
71
+ else if (req.url === "/api/v4/posts" && req.method === "POST") {
72
+ let body = "";
73
+ req.on("data", (c) => (body += c));
74
+ req.on("end", () => {
75
+ posts.push(JSON.parse(body));
76
+ res.writeHead(201).end(JSON.stringify({ id: "reply1" }));
77
+ });
78
+ }
79
+ else {
80
+ res.writeHead(404).end("{}");
81
+ }
82
+ });
83
+ const wss = new WebSocketServer({ noServer: true });
84
+ let current;
85
+ http.on("upgrade", (req, sock, head) => {
86
+ wss.handleUpgrade(req, sock, head, (ws) => {
87
+ current = ws;
88
+ ws.on("message", (raw) => {
89
+ const f = JSON.parse(raw.toString());
90
+ if (f.action === "authentication_challenge") {
91
+ ws.send(JSON.stringify({ seq_reply: f.seq, status: "OK" }));
92
+ ws.send(JSON.stringify({ event: "hello", data: {} }));
93
+ }
94
+ });
95
+ });
96
+ });
97
+ await new Promise((r) => http.listen(0, "127.0.0.1", r));
98
+ cleanups.push(() => new Promise((r) => {
99
+ for (const c of wss.clients)
100
+ c.terminate();
101
+ http.close(() => r());
102
+ }));
103
+ return { url: `http://127.0.0.1:${http.address().port}`, posts, socket: () => current };
104
+ }
105
+ describe("goshti-channel as Claude Code runs it", { timeout: 30_000 }, () => {
106
+ it("declares the channel capability and the reply tool", async () => {
107
+ const { client } = await start(home(null));
108
+ expect(client.getServerCapabilities()?.experimental).toHaveProperty("claude/channel");
109
+ const tools = await client.listTools();
110
+ expect(tools.tools.map((t) => t.name)).toEqual(["goshti_reply"]);
111
+ });
112
+ it("tells the session it is not set up, rather than idling silently", async () => {
113
+ const { notes } = await start(home(null));
114
+ await until(() => notes.length > 0);
115
+ expect(notes[0].meta).toMatchObject({ source: "goshti", status: "offline", reason: "not_configured" });
116
+ expect(notes[0].content).toMatch(/goshti-channel setup/);
117
+ });
118
+ // Spec: "Token revoked".
119
+ it("tells the session the channel is offline when the token is refused", async () => {
120
+ const g = await goshti({ refuse: true });
121
+ const { notes } = await start(home({ url: g.url }));
122
+ await until(() => notes.length > 0);
123
+ expect(notes[0].meta).toMatchObject({ status: "offline", reason: "token_refused" });
124
+ expect(notes[0].content).toMatch(/revoked|expired/);
125
+ });
126
+ it("delivers the person's trigger and answers in its thread, marked", async () => {
127
+ const g = await goshti();
128
+ const { client, notes } = await start(home({ url: g.url }));
129
+ await until(() => g.socket() !== undefined);
130
+ // Give the hello a moment to land before posting.
131
+ await new Promise((r) => setTimeout(r, 200));
132
+ g.socket().send(JSON.stringify({
133
+ event: "posted",
134
+ data: {
135
+ post: JSON.stringify({ id: "p1", channel_id: "c1", user_id: "me1", root_id: "", message: "@claude hello", type: "", props: {} }),
136
+ channel_type: "O",
137
+ channel_name: "town-square",
138
+ sender_name: "@sumit",
139
+ },
140
+ }));
141
+ g.socket().send(JSON.stringify({
142
+ event: "posted",
143
+ data: {
144
+ post: JSON.stringify({ id: "p2", channel_id: "c1", user_id: "col1", root_id: "", message: "@claude rm -rf", type: "", props: {} }),
145
+ channel_type: "O",
146
+ channel_name: "town-square",
147
+ sender_name: "@alice",
148
+ },
149
+ }));
150
+ await until(() => notes.some((n) => n.meta.post_id === "p1"));
151
+ await new Promise((r) => setTimeout(r, 200));
152
+ expect(notes.filter((n) => n.meta.type === "post").map((n) => n.meta.post_id)).toEqual(["p1"]);
153
+ const refused = await client.callTool({ name: "goshti_reply", arguments: { post_id: "p2", text: "no" } });
154
+ expect(refused.isError).toBe(true);
155
+ expect(g.posts).toHaveLength(0);
156
+ const ok = await client.callTool({ name: "goshti_reply", arguments: { post_id: "p1", text: "Hi!" } });
157
+ expect(ok.isError).toBe(false);
158
+ expect(g.posts).toHaveLength(1);
159
+ expect(g.posts[0]).toMatchObject({ channel_id: "c1", root_id: "p1", props: { from_claude: "true" } });
160
+ expect(String(g.posts[0].message)).toMatch(/^Hi![\s\S]*via Claude, for @sumit/);
161
+ });
162
+ });
163
+ //# sourceMappingURL=e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2e.test.js","sourceRoot":"","sources":["../../src/goshtiChannel/e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * The post property every reply carries, so this channel never delivers its
3
+ * own reply back to the session (the person's own post, often in their own
4
+ * direct conversation, quoting the trigger word) and readers and exports can
5
+ * tell a generated answer from a typed one.
6
+ *
7
+ * The connector's marker (task 1.5) is not built yet; when it is, the two
8
+ * should agree on this name.
9
+ */
10
+ export declare const MARKER_PROP = "from_claude";
11
+ /** The chat server rejects a post longer than 16,383 characters. */
12
+ export declare const MAX_REPLY_CHARS = 16000;
13
+ /** The longest triggering message passed to the session as is. */
14
+ export declare const MAX_TRIGGER_CHARS = 8000;
15
+ export interface ChannelPost {
16
+ id: string;
17
+ channelId: string;
18
+ userId: string;
19
+ rootId: string;
20
+ message: string;
21
+ /** Non-empty for system messages ("joined the channel"). */
22
+ type: string;
23
+ props: Record<string, unknown>;
24
+ createAt: number;
25
+ }
26
+ export interface PostedEvent {
27
+ post: ChannelPost;
28
+ /** "O" public, "P" private, "D" direct, "G" group. */
29
+ channelType: string;
30
+ channelName: string;
31
+ channelDisplayName?: string;
32
+ /** The poster's @name, as the server sends it. */
33
+ senderName: string;
34
+ }
35
+ export interface Me {
36
+ id: string;
37
+ username: string;
38
+ }
39
+ export interface Allowlist {
40
+ users: string[];
41
+ channels: string[];
42
+ }
43
+ export interface TriggerConfig {
44
+ trigger: string;
45
+ allow: Allowlist;
46
+ }
47
+ export type Decision = {
48
+ deliver: true;
49
+ reason: "own_trigger" | "self_dm" | "allowlisted";
50
+ thirdParty: boolean;
51
+ } | {
52
+ deliver: false;
53
+ reason: "system" | "webhook" | "bot" | "own_reply" | "no_trigger" | "not_allowlisted" | "sender_unknown";
54
+ };
55
+ /**
56
+ * A `posted` WebSocket event, or null for one with no readable post. The post
57
+ * itself arrives as a JSON string inside the event's data.
58
+ */
59
+ export declare function parsePostedEvent(data: Record<string, unknown>): PostedEvent | null;
60
+ /**
61
+ * Whether a message contains the trigger word, as a word of its own: not part
62
+ * of a longer name (`@claudebot`, `@claude.team`) or an address (`x@claude.ai`).
63
+ */
64
+ export declare function hasTrigger(message: string, trigger: string): boolean;
65
+ /** Whether the event is in the person's direct conversation with themselves. */
66
+ export declare function isSelfDirect(ev: PostedEvent, me: Me): boolean;
67
+ /**
68
+ * Whether a post may be delivered to the session.
69
+ *
70
+ * `senderIsBot` is the sender's account as the server reports it: true, false,
71
+ * or undefined when it could not be looked up. Unknown is refused — an
72
+ * allowlist is a statement about people, and a sender who cannot be shown to
73
+ * be one is not let through on the strength of it.
74
+ */
75
+ export declare function decide(ev: PostedEvent, me: Me, cfg: TriggerConfig, senderIsBot: boolean | undefined): Decision;
76
+ /**
77
+ * Someone else's words, framed so they read as information and not as
78
+ * instructions. The text cannot close its own wrapper: any occurrence of the
79
+ * tag inside it is defused.
80
+ */
81
+ export declare function wrapThirdParty(text: string, who: {
82
+ author: string;
83
+ userId: string;
84
+ }): string;
85
+ export interface ContextPost {
86
+ id: string;
87
+ userId: string;
88
+ message: string;
89
+ createAt: number;
90
+ }
91
+ export interface BoundedContext {
92
+ included: Array<ContextPost & {
93
+ truncated: boolean;
94
+ }>;
95
+ /** Posts in the thread that were left out. */
96
+ omitted: number;
97
+ }
98
+ /**
99
+ * The thread context sent with a delivery: the posts before the trigger, the
100
+ * most recent `maxPosts` of them, within `maxChars` in all (oldest dropped
101
+ * first), each one cut to a size of its own.
102
+ */
103
+ export declare function boundContext(posts: ContextPost[], triggerId: string, bounds: {
104
+ maxPosts: number;
105
+ maxChars: number;
106
+ }): BoundedContext;
107
+ export interface ThreadTarget {
108
+ channelId: string;
109
+ rootId: string;
110
+ }
111
+ /**
112
+ * The threads this session may answer in: those that produced a delivery.
113
+ * Held in memory only, so a restarted session starts with none.
114
+ */
115
+ export declare class ReplyGuard {
116
+ private readonly byPost;
117
+ record(post: {
118
+ id: string;
119
+ channelId: string;
120
+ rootId: string;
121
+ }): void;
122
+ resolve(postId: string): ThreadTarget | null;
123
+ }
124
+ /** A reply as posted: the visible marker added, the property set, the size held. */
125
+ export declare function markReply(text: string, me: Me): {
126
+ message: string;
127
+ props: Record<string, string>;
128
+ truncated: boolean;
129
+ };
130
+ /**
131
+ * Fixed-period delivery cap. A period opens on the first delivery after the
132
+ * last one closed; what arrives over the cap is counted, not queued, and the
133
+ * count is handed out once, after its period ends.
134
+ */
135
+ export declare class RateGate {
136
+ private readonly max;
137
+ private readonly periodMs;
138
+ private readonly now;
139
+ private start;
140
+ private count;
141
+ private held;
142
+ private pending;
143
+ constructor(max: number, periodMs: number, now?: () => number);
144
+ private roll;
145
+ admit(): boolean;
146
+ /** When the open period ends, or null when none is open. */
147
+ periodEndsAt(): number | null;
148
+ /** The number held back in periods that have ended, once; null if none. */
149
+ takeSummary(): {
150
+ held: number;
151
+ periodMs: number;
152
+ } | null;
153
+ }
154
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/goshtiChannel/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ // The rules of the Goshti channel (add-goshti-claude-connector, design Part 2).
2
+ //
3
+ // A channel pushes other people's text into a session that can run tools on
4
+ // the person's machine. Treated carelessly that is remote prompt injection by
5
+ // anyone who can post where the person can read. Everything here is pure, so
6
+ // each rule is tested on its own and the I/O around it cannot quietly bend one:
7
+ //
8
+ // 1. Only the person's own posts trigger by default — the trigger word in a
9
+ // post, or anything in their direct conversation with themselves.
10
+ // 2. Another sender is delivered only when both they and the channel are in
11
+ // the local allowlist. Bots and webhooks never, allowlisted or not.
12
+ // 3. Anyone else's text is wrapped and labelled as untrusted.
13
+ // 4. Thread context is bounded: last N posts, a character cap.
14
+ // 5. A reply goes only into a thread that produced a delivery this session.
15
+ // 6. Deliveries are capped per period; over it, one summary.
16
+ /**
17
+ * The post property every reply carries, so this channel never delivers its
18
+ * own reply back to the session (the person's own post, often in their own
19
+ * direct conversation, quoting the trigger word) and readers and exports can
20
+ * tell a generated answer from a typed one.
21
+ *
22
+ * The connector's marker (task 1.5) is not built yet; when it is, the two
23
+ * should agree on this name.
24
+ */
25
+ export const MARKER_PROP = "from_claude";
26
+ /** The chat server rejects a post longer than 16,383 characters. */
27
+ export const MAX_REPLY_CHARS = 16_000;
28
+ /** The longest triggering message passed to the session as is. */
29
+ export const MAX_TRIGGER_CHARS = 8_000;
30
+ /** The longest single post of thread context. */
31
+ const MAX_CONTEXT_POST_CHARS = 2_000;
32
+ const str = (v) => (typeof v === "string" ? v : "");
33
+ const truthy = (v) => v === true || v === "true";
34
+ /**
35
+ * A `posted` WebSocket event, or null for one with no readable post. The post
36
+ * itself arrives as a JSON string inside the event's data.
37
+ */
38
+ export function parsePostedEvent(data) {
39
+ const raw = data.post;
40
+ if (typeof raw !== "string" || raw === "")
41
+ return null;
42
+ let p;
43
+ try {
44
+ p = JSON.parse(raw);
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ if (!p || typeof p !== "object" || !str(p.id) || !str(p.user_id) || !str(p.channel_id))
50
+ return null;
51
+ const props = p.props && typeof p.props === "object" ? p.props : {};
52
+ const out = {
53
+ post: {
54
+ id: str(p.id),
55
+ channelId: str(p.channel_id),
56
+ userId: str(p.user_id),
57
+ rootId: str(p.root_id),
58
+ message: str(p.message),
59
+ type: str(p.type),
60
+ props,
61
+ createAt: typeof p.create_at === "number" ? p.create_at : 0,
62
+ },
63
+ channelType: str(data.channel_type),
64
+ channelName: str(data.channel_name),
65
+ senderName: str(data.sender_name),
66
+ };
67
+ const display = str(data.channel_display_name);
68
+ if (display)
69
+ out.channelDisplayName = display;
70
+ return out;
71
+ }
72
+ function escapeRegex(s) {
73
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
74
+ }
75
+ /**
76
+ * Whether a message contains the trigger word, as a word of its own: not part
77
+ * of a longer name (`@claudebot`, `@claude.team`) or an address (`x@claude.ai`).
78
+ */
79
+ export function hasTrigger(message, trigger) {
80
+ const t = trigger.trim();
81
+ if (!t)
82
+ return false;
83
+ const re = new RegExp(`(^|[^\\w@.-])${escapeRegex(t)}(?![\\w-]|\\.\\w)`, "i");
84
+ return re.test(message);
85
+ }
86
+ /** Whether the event is in the person's direct conversation with themselves. */
87
+ export function isSelfDirect(ev, me) {
88
+ return ev.channelType === "D" && ev.channelName === `${me.id}__${me.id}`;
89
+ }
90
+ /**
91
+ * Whether a post may be delivered to the session.
92
+ *
93
+ * `senderIsBot` is the sender's account as the server reports it: true, false,
94
+ * or undefined when it could not be looked up. Unknown is refused — an
95
+ * allowlist is a statement about people, and a sender who cannot be shown to
96
+ * be one is not let through on the strength of it.
97
+ */
98
+ export function decide(ev, me, cfg, senderIsBot) {
99
+ const { post } = ev;
100
+ if (post.type !== "")
101
+ return { deliver: false, reason: "system" };
102
+ if (truthy(post.props.from_webhook))
103
+ return { deliver: false, reason: "webhook" };
104
+ if (truthy(post.props.from_bot))
105
+ return { deliver: false, reason: "bot" };
106
+ if (truthy(post.props[MARKER_PROP]))
107
+ return { deliver: false, reason: "own_reply" };
108
+ if (post.userId === me.id) {
109
+ if (isSelfDirect(ev, me))
110
+ return { deliver: true, reason: "self_dm", thirdParty: false };
111
+ if (hasTrigger(post.message, cfg.trigger)) {
112
+ return { deliver: true, reason: "own_trigger", thirdParty: false };
113
+ }
114
+ return { deliver: false, reason: "no_trigger" };
115
+ }
116
+ if (!cfg.allow.users.includes(post.userId) || !cfg.allow.channels.includes(post.channelId)) {
117
+ return { deliver: false, reason: "not_allowlisted" };
118
+ }
119
+ if (senderIsBot === undefined)
120
+ return { deliver: false, reason: "sender_unknown" };
121
+ if (senderIsBot)
122
+ return { deliver: false, reason: "bot" };
123
+ if (!hasTrigger(post.message, cfg.trigger))
124
+ return { deliver: false, reason: "no_trigger" };
125
+ return { deliver: true, reason: "allowlisted", thirdParty: true };
126
+ }
127
+ const WRAP_TAG = "untrusted_third_party_text";
128
+ function attr(s) {
129
+ return s.replace(/[^\w@.\- ]/g, "");
130
+ }
131
+ /**
132
+ * Someone else's words, framed so they read as information and not as
133
+ * instructions. The text cannot close its own wrapper: any occurrence of the
134
+ * tag inside it is defused.
135
+ */
136
+ export function wrapThirdParty(text, who) {
137
+ const defused = text.replace(new RegExp(`<\\s*(/?)\\s*${WRAP_TAG}`, "gi"), (_m, slash) => `<${slash}_${WRAP_TAG}`);
138
+ return `<${WRAP_TAG} author="${attr(who.author)}" user_id="${attr(who.userId)}">\n${defused}\n</${WRAP_TAG}>`;
139
+ }
140
+ /**
141
+ * The thread context sent with a delivery: the posts before the trigger, the
142
+ * most recent `maxPosts` of them, within `maxChars` in all (oldest dropped
143
+ * first), each one cut to a size of its own.
144
+ */
145
+ export function boundContext(posts, triggerId, bounds) {
146
+ const candidates = posts
147
+ .filter((p) => p.id !== triggerId)
148
+ .sort((a, b) => a.createAt - b.createAt);
149
+ const perPost = Math.max(1, Math.min(bounds.maxChars, MAX_CONTEXT_POST_CHARS));
150
+ const recent = candidates.slice(Math.max(0, candidates.length - bounds.maxPosts));
151
+ const included = [];
152
+ let total = 0;
153
+ for (let i = recent.length - 1; i >= 0; i--) {
154
+ const p = recent[i];
155
+ const cut = p.message.length > perPost;
156
+ const message = cut ? p.message.slice(0, perPost) : p.message;
157
+ if (total + message.length > bounds.maxChars)
158
+ break;
159
+ total += message.length;
160
+ included.unshift({ ...p, message, truncated: cut });
161
+ }
162
+ return { included, omitted: candidates.length - included.length };
163
+ }
164
+ /**
165
+ * The threads this session may answer in: those that produced a delivery.
166
+ * Held in memory only, so a restarted session starts with none.
167
+ */
168
+ export class ReplyGuard {
169
+ byPost = new Map();
170
+ record(post) {
171
+ const target = { channelId: post.channelId, rootId: post.rootId || post.id };
172
+ this.byPost.set(post.id, target);
173
+ this.byPost.set(target.rootId, target);
174
+ }
175
+ resolve(postId) {
176
+ if (!postId)
177
+ return null;
178
+ return this.byPost.get(postId) ?? null;
179
+ }
180
+ }
181
+ /** A reply as posted: the visible marker added, the property set, the size held. */
182
+ export function markReply(text, me) {
183
+ const marker = `\n\n_— via Claude, for @${me.username}_`;
184
+ const room = MAX_REPLY_CHARS - marker.length - 2;
185
+ const truncated = text.length > room;
186
+ const body = truncated ? `${text.slice(0, room)}…` : text;
187
+ return { message: `${body}${marker}`, props: { [MARKER_PROP]: "true" }, truncated };
188
+ }
189
+ /**
190
+ * Fixed-period delivery cap. A period opens on the first delivery after the
191
+ * last one closed; what arrives over the cap is counted, not queued, and the
192
+ * count is handed out once, after its period ends.
193
+ */
194
+ export class RateGate {
195
+ max;
196
+ periodMs;
197
+ now;
198
+ start = null;
199
+ count = 0;
200
+ held = 0;
201
+ pending = 0;
202
+ constructor(max, periodMs, now = () => Date.now()) {
203
+ this.max = max;
204
+ this.periodMs = periodMs;
205
+ this.now = now;
206
+ }
207
+ roll() {
208
+ if (this.start !== null && this.now() >= this.start + this.periodMs) {
209
+ this.pending += this.held;
210
+ this.start = null;
211
+ this.count = 0;
212
+ this.held = 0;
213
+ }
214
+ }
215
+ admit() {
216
+ this.roll();
217
+ if (this.start === null)
218
+ this.start = this.now();
219
+ if (this.count < this.max) {
220
+ this.count++;
221
+ return true;
222
+ }
223
+ this.held++;
224
+ return false;
225
+ }
226
+ /** When the open period ends, or null when none is open. */
227
+ periodEndsAt() {
228
+ return this.start === null ? null : this.start + this.periodMs;
229
+ }
230
+ /** The number held back in periods that have ended, once; null if none. */
231
+ takeSummary() {
232
+ this.roll();
233
+ if (this.pending === 0)
234
+ return null;
235
+ const held = this.pending;
236
+ this.pending = 0;
237
+ return { held, periodMs: this.periodMs };
238
+ }
239
+ }
240
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/goshtiChannel/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.test.d.ts","sourceRoot":"","sources":["../../src/goshtiChannel/policy.test.ts"],"names":[],"mappings":""}