@agent-relay/hooks 0.1.0

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 (41) hide show
  1. package/dist/browser.d.ts +2 -0
  2. package/dist/browser.d.ts.map +1 -0
  3. package/dist/browser.js +3 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/emitter.d.ts +40 -0
  6. package/dist/emitter.d.ts.map +1 -0
  7. package/dist/emitter.js +63 -0
  8. package/dist/emitter.js.map +1 -0
  9. package/dist/inbox-check/hook.d.ts +28 -0
  10. package/dist/inbox-check/hook.d.ts.map +1 -0
  11. package/dist/inbox-check/hook.js +97 -0
  12. package/dist/inbox-check/hook.js.map +1 -0
  13. package/dist/inbox-check/index.d.ts +8 -0
  14. package/dist/inbox-check/index.d.ts.map +1 -0
  15. package/dist/inbox-check/index.js +8 -0
  16. package/dist/inbox-check/index.js.map +1 -0
  17. package/dist/inbox-check/types.d.ts +31 -0
  18. package/dist/inbox-check/types.d.ts.map +1 -0
  19. package/dist/inbox-check/types.js +5 -0
  20. package/dist/inbox-check/types.js.map +1 -0
  21. package/dist/inbox-check/utils.d.ts +44 -0
  22. package/dist/inbox-check/utils.d.ts.map +1 -0
  23. package/dist/inbox-check/utils.js +107 -0
  24. package/dist/inbox-check/utils.js.map +1 -0
  25. package/dist/index.d.ts +11 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +11 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/registry.d.ts +173 -0
  30. package/dist/registry.d.ts.map +1 -0
  31. package/dist/registry.js +476 -0
  32. package/dist/registry.js.map +1 -0
  33. package/dist/trajectory-hooks.d.ts +52 -0
  34. package/dist/trajectory-hooks.d.ts.map +1 -0
  35. package/dist/trajectory-hooks.js +183 -0
  36. package/dist/trajectory-hooks.js.map +1 -0
  37. package/dist/types.d.ts +285 -0
  38. package/dist/types.d.ts.map +1 -0
  39. package/dist/types.js +10 -0
  40. package/dist/types.js.map +1 -0
  41. package/package.json +52 -0
@@ -0,0 +1,2 @@
1
+ export * from './types.js';
2
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Browser-safe entry: types only, no Node dependencies
2
+ export * from './types.js';
3
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,cAAc,YAAY,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * HookEmitter
3
+ *
4
+ * Lightweight async event emitter for hook handlers.
5
+ * - Supports async handlers
6
+ * - Allows stop-propagation via `{ stop: true }` return value
7
+ * - Can preload handlers from a config object
8
+ */
9
+ export type EmitterHandlerResult = unknown | {
10
+ stop?: boolean;
11
+ };
12
+ export type EmitterHandler = (...args: unknown[]) => EmitterHandlerResult | Promise<EmitterHandlerResult>;
13
+ export interface EmitResult {
14
+ /** Raw results from each handler in order */
15
+ results: EmitterHandlerResult[];
16
+ /** Whether propagation was stopped by a handler */
17
+ stopped: boolean;
18
+ }
19
+ export type EmitterHandlerConfig = Record<string, EmitterHandler | EmitterHandler[]>;
20
+ export declare class HookEmitter {
21
+ private handlers;
22
+ constructor(config?: EmitterHandlerConfig);
23
+ /**
24
+ * Register a handler for an event.
25
+ * Returns an unsubscribe function to remove the handler.
26
+ */
27
+ on(event: string, handler: EmitterHandler): () => void;
28
+ /**
29
+ * Emit an event and invoke handlers sequentially.
30
+ * If a handler returns `{ stop: true }`, propagation halts.
31
+ */
32
+ emit(event: string, ...args: unknown[]): Promise<EmitResult>;
33
+ /**
34
+ * Load handlers from a configuration object.
35
+ * Values can be a single handler or an array of handlers.
36
+ */
37
+ load(config: EmitterHandlerConfig): void;
38
+ private shouldStop;
39
+ }
40
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../src/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAE1G,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,EAAE,CAAC,CAAC;AAErF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAuC;gBAE3C,MAAM,CAAC,EAAE,oBAAoB;IAMzC;;;OAGG;IACH,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,IAAI;IAWtD;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAkBlE;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IASxC,OAAO,CAAC,UAAU;CAGnB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * HookEmitter
3
+ *
4
+ * Lightweight async event emitter for hook handlers.
5
+ * - Supports async handlers
6
+ * - Allows stop-propagation via `{ stop: true }` return value
7
+ * - Can preload handlers from a config object
8
+ */
9
+ export class HookEmitter {
10
+ handlers = new Map();
11
+ constructor(config) {
12
+ if (config) {
13
+ this.load(config);
14
+ }
15
+ }
16
+ /**
17
+ * Register a handler for an event.
18
+ * Returns an unsubscribe function to remove the handler.
19
+ */
20
+ on(event, handler) {
21
+ const list = this.handlers.get(event) ?? [];
22
+ list.push(handler);
23
+ this.handlers.set(event, list);
24
+ return () => {
25
+ const updated = this.handlers.get(event)?.filter((fn) => fn !== handler) ?? [];
26
+ this.handlers.set(event, updated);
27
+ };
28
+ }
29
+ /**
30
+ * Emit an event and invoke handlers sequentially.
31
+ * If a handler returns `{ stop: true }`, propagation halts.
32
+ */
33
+ async emit(event, ...args) {
34
+ const results = [];
35
+ const handlers = this.handlers.get(event) ?? [];
36
+ let stopped = false;
37
+ for (const handler of handlers) {
38
+ const result = await handler(...args);
39
+ results.push(result);
40
+ if (this.shouldStop(result)) {
41
+ stopped = true;
42
+ break;
43
+ }
44
+ }
45
+ return { results, stopped };
46
+ }
47
+ /**
48
+ * Load handlers from a configuration object.
49
+ * Values can be a single handler or an array of handlers.
50
+ */
51
+ load(config) {
52
+ for (const [event, handler] of Object.entries(config)) {
53
+ const handlers = Array.isArray(handler) ? handler : [handler];
54
+ for (const h of handlers) {
55
+ this.on(event, h);
56
+ }
57
+ }
58
+ }
59
+ shouldStop(result) {
60
+ return typeof result === 'object' && result !== null && 'stop' in result && result.stop === true;
61
+ }
62
+ }
63
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../src/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,MAAM,OAAO,WAAW;IACd,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEvD,YAAY,MAA6B;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,EAAE,CAAC,KAAa,EAAE,OAAuB;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAE/B,OAAO,GAAG,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/E,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,GAAG,IAAe;QAC1C,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAErB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM;YACR,CAAC;QACH,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,MAA4B;QAC/B,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC9D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,MAA4B;QAC7C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,MAAM,IAAK,MAAc,CAAC,IAAI,KAAK,IAAI,CAAC;IAC5G,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent Relay Inbox Check Hook
4
+ *
5
+ * A Claude Code Stop hook that checks for unread messages in the agent-relay inbox.
6
+ * When messages are present, it blocks Claude from stopping and instructs it to
7
+ * read and respond to the messages.
8
+ *
9
+ * This enables autonomous agent-to-agent communication without human intervention.
10
+ *
11
+ * Usage in .claude/settings.json:
12
+ * {
13
+ * "hooks": {
14
+ * "Stop": [{
15
+ * "hooks": [{
16
+ * "type": "command",
17
+ * "command": "node /path/to/agent-relay/dist/hooks/inbox-check/hook.js"
18
+ * }]
19
+ * }]
20
+ * }
21
+ * }
22
+ *
23
+ * Environment Variables:
24
+ * - AGENT_RELAY_NAME: The agent's name (set by agent-relay wrapper)
25
+ * - AGENT_RELAY_INBOX_DIR: Custom inbox directory (default: /tmp/agent-relay)
26
+ */
27
+ export {};
28
+ //# sourceMappingURL=hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/inbox-check/hook.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG"}
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Agent Relay Inbox Check Hook
4
+ *
5
+ * A Claude Code Stop hook that checks for unread messages in the agent-relay inbox.
6
+ * When messages are present, it blocks Claude from stopping and instructs it to
7
+ * read and respond to the messages.
8
+ *
9
+ * This enables autonomous agent-to-agent communication without human intervention.
10
+ *
11
+ * Usage in .claude/settings.json:
12
+ * {
13
+ * "hooks": {
14
+ * "Stop": [{
15
+ * "hooks": [{
16
+ * "type": "command",
17
+ * "command": "node /path/to/agent-relay/dist/hooks/inbox-check/hook.js"
18
+ * }]
19
+ * }]
20
+ * }
21
+ * }
22
+ *
23
+ * Environment Variables:
24
+ * - AGENT_RELAY_NAME: The agent's name (set by agent-relay wrapper)
25
+ * - AGENT_RELAY_INBOX_DIR: Custom inbox directory (default: /tmp/agent-relay)
26
+ */
27
+ import { readFileSync } from 'node:fs';
28
+ import { DEFAULT_INBOX_DIR, getAgentName, getInboxPath, hasUnreadMessages, countMessages, buildBlockReason } from './utils.js';
29
+ /**
30
+ * Read hook input from stdin
31
+ */
32
+ function readStdin() {
33
+ try {
34
+ const input = readFileSync(0, 'utf-8');
35
+ return JSON.parse(input);
36
+ }
37
+ catch {
38
+ return {};
39
+ }
40
+ }
41
+ /**
42
+ * Output hook result as JSON
43
+ */
44
+ function outputResult(result) {
45
+ console.log(JSON.stringify(result));
46
+ }
47
+ /**
48
+ * Exit the hook process
49
+ */
50
+ function exitHook(code) {
51
+ process.exit(code);
52
+ }
53
+ /**
54
+ * Main hook execution
55
+ */
56
+ async function main() {
57
+ try {
58
+ // Read stdin (required by Claude Code hook protocol, but we only use env vars)
59
+ readStdin();
60
+ // Get agent name from env
61
+ const agentName = getAgentName();
62
+ // If no agent name configured, allow stop (not in relay mode)
63
+ if (!agentName) {
64
+ outputResult({ decision: 'approve' });
65
+ exitHook(0);
66
+ }
67
+ // Get inbox configuration
68
+ const inboxDir = process.env.AGENT_RELAY_INBOX_DIR || DEFAULT_INBOX_DIR;
69
+ const inboxPath = getInboxPath({ inboxDir, agentName });
70
+ // Check for unread messages
71
+ if (hasUnreadMessages(inboxPath)) {
72
+ const messageCount = countMessages(inboxPath);
73
+ const reason = buildBlockReason(inboxPath, messageCount);
74
+ // Log to stderr for visibility
75
+ console.error(`[agent-relay] Found ${messageCount} unread message(s), blocking stop`);
76
+ // Block stop and provide reason
77
+ outputResult({
78
+ decision: 'block',
79
+ reason
80
+ });
81
+ }
82
+ else {
83
+ // No messages, allow stop
84
+ outputResult({ decision: 'approve' });
85
+ }
86
+ exitHook(0);
87
+ }
88
+ catch (error) {
89
+ // On error, allow stop to avoid blocking user
90
+ console.error('[agent-relay] Hook error:', error);
91
+ outputResult({ decision: 'approve' });
92
+ exitHook(0);
93
+ }
94
+ }
95
+ // Run the hook
96
+ main();
97
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/inbox-check/hook.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,MAAkB;IACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,+EAA+E;QAC/E,SAAS,EAAE,CAAC;QAEZ,0BAA0B;QAC1B,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;QAEjC,8DAA8D;QAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;YACtC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;QAED,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,iBAAiB,CAAC;QACxE,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QAExD,4BAA4B;QAC5B,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,YAAY,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YAEzD,+BAA+B;YAC/B,OAAO,CAAC,KAAK,CAAC,uBAAuB,YAAY,mCAAmC,CAAC,CAAC;YAEtF,gCAAgC;YAChC,YAAY,CAAC;gBACX,QAAQ,EAAE,OAAO;gBACjB,MAAM;aACP,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACxC,CAAC;QAED,QAAQ,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8CAA8C;QAC9C,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QAClD,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACtC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,eAAe;AACf,IAAI,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Agent Relay Inbox Check Hook
3
+ *
4
+ * Exports for programmatic use of the hook utilities.
5
+ */
6
+ export * from './types.js';
7
+ export * from './utils.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/inbox-check/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Agent Relay Inbox Check Hook
3
+ *
4
+ * Exports for programmatic use of the hook utilities.
5
+ */
6
+ export * from './types.js';
7
+ export * from './utils.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/inbox-check/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Types for Agent Relay Inbox Check Hook
3
+ */
4
+ export interface HookInput {
5
+ /** The hook event type */
6
+ hook_event_name?: string;
7
+ /** Working directory */
8
+ workingDirectory?: string;
9
+ /** Session ID */
10
+ session_id?: string;
11
+ /** Stop reason from Claude */
12
+ stop_reason?: string;
13
+ }
14
+ export interface HookOutput {
15
+ /** Decision: "approve" to allow stop, "block" to continue */
16
+ decision: 'approve' | 'block';
17
+ /** Reason for the decision (shown to Claude if blocked) */
18
+ reason?: string;
19
+ }
20
+ export interface InboxMessage {
21
+ from: string;
22
+ timestamp: string;
23
+ body: string;
24
+ }
25
+ export interface InboxConfig {
26
+ /** Base directory for inbox files */
27
+ inboxDir: string;
28
+ /** Agent name (from env var or config) */
29
+ agentName?: string;
30
+ }
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/inbox-check/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wBAAwB;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,6DAA6D;IAC7D,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Types for Agent Relay Inbox Check Hook
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/inbox-check/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Utility functions for Agent Relay Inbox Check Hook
3
+ */
4
+ import type { InboxConfig, InboxMessage } from './types.js';
5
+ /** Default inbox directory */
6
+ export declare const DEFAULT_INBOX_DIR = "/tmp/agent-relay";
7
+ /**
8
+ * Get the agent name from environment or config
9
+ */
10
+ export declare function getAgentName(): string | undefined;
11
+ /**
12
+ * Get the inbox file path for an agent
13
+ */
14
+ export declare function getInboxPath(config: InboxConfig): string;
15
+ /**
16
+ * Check if inbox file exists and has content
17
+ */
18
+ export declare function inboxExists(inboxPath: string): boolean;
19
+ /**
20
+ * Read inbox file content
21
+ */
22
+ export declare function readInbox(inboxPath: string): string;
23
+ /**
24
+ * Check if inbox has unread messages
25
+ * Messages are marked with "## Message from" header
26
+ */
27
+ export declare function hasUnreadMessages(inboxPath: string): boolean;
28
+ /**
29
+ * Count unread messages in inbox
30
+ */
31
+ export declare function countMessages(inboxPath: string): number;
32
+ /**
33
+ * Parse messages from inbox content
34
+ */
35
+ export declare function parseMessages(inboxPath: string): InboxMessage[];
36
+ /**
37
+ * Format a message for display
38
+ */
39
+ export declare function formatMessagePreview(msg: InboxMessage, maxLength?: number): string;
40
+ /**
41
+ * Build the block reason message
42
+ */
43
+ export declare function buildBlockReason(inboxPath: string, messageCount: number): string;
44
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/inbox-check/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE5D,8BAA8B;AAC9B,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAGjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAMxD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CAmB/D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,GAAE,MAAW,GAAG,MAAM,CAKtF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAehF"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Utility functions for Agent Relay Inbox Check Hook
3
+ */
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ /** Default inbox directory */
7
+ export const DEFAULT_INBOX_DIR = '/tmp/agent-relay';
8
+ /**
9
+ * Get the agent name from environment or config
10
+ */
11
+ export function getAgentName() {
12
+ // Check environment variable set by agent-relay wrapper
13
+ return process.env.AGENT_RELAY_NAME;
14
+ }
15
+ /**
16
+ * Get the inbox file path for an agent
17
+ */
18
+ export function getInboxPath(config) {
19
+ const agentName = config.agentName || getAgentName();
20
+ if (!agentName) {
21
+ throw new Error('Agent name not configured. Set AGENT_RELAY_NAME env var.');
22
+ }
23
+ return join(config.inboxDir, agentName, 'inbox.md');
24
+ }
25
+ /**
26
+ * Check if inbox file exists and has content
27
+ */
28
+ export function inboxExists(inboxPath) {
29
+ return existsSync(inboxPath);
30
+ }
31
+ /**
32
+ * Read inbox file content
33
+ */
34
+ export function readInbox(inboxPath) {
35
+ if (!inboxExists(inboxPath)) {
36
+ return '';
37
+ }
38
+ return readFileSync(inboxPath, 'utf-8');
39
+ }
40
+ /**
41
+ * Check if inbox has unread messages
42
+ * Messages are marked with "## Message from" header
43
+ */
44
+ export function hasUnreadMessages(inboxPath) {
45
+ const content = readInbox(inboxPath);
46
+ if (!content || !content.trim()) {
47
+ return false;
48
+ }
49
+ // Check for message headers
50
+ return content.includes('## Message from');
51
+ }
52
+ /**
53
+ * Count unread messages in inbox
54
+ */
55
+ export function countMessages(inboxPath) {
56
+ const content = readInbox(inboxPath);
57
+ if (!content) {
58
+ return 0;
59
+ }
60
+ const matches = content.match(/## Message from/g);
61
+ return matches ? matches.length : 0;
62
+ }
63
+ /**
64
+ * Parse messages from inbox content
65
+ */
66
+ export function parseMessages(inboxPath) {
67
+ const content = readInbox(inboxPath);
68
+ if (!content) {
69
+ return [];
70
+ }
71
+ const messages = [];
72
+ const messageBlocks = content.split(/(?=## Message from)/);
73
+ for (const block of messageBlocks) {
74
+ const headerMatch = block.match(/## Message from (\S+) \| (.+)\n/);
75
+ if (headerMatch) {
76
+ const [, from, timestamp] = headerMatch;
77
+ const body = block.replace(/## Message from .+\n/, '').trim();
78
+ messages.push({ from, timestamp, body });
79
+ }
80
+ }
81
+ return messages;
82
+ }
83
+ /**
84
+ * Format a message for display
85
+ */
86
+ export function formatMessagePreview(msg, maxLength = 50) {
87
+ const preview = msg.body.length > maxLength
88
+ ? msg.body.substring(0, maxLength) + '...'
89
+ : msg.body;
90
+ return `[${msg.from}]: ${preview}`;
91
+ }
92
+ /**
93
+ * Build the block reason message
94
+ */
95
+ export function buildBlockReason(inboxPath, messageCount) {
96
+ const messages = parseMessages(inboxPath);
97
+ const previews = messages.slice(0, 3).map(m => formatMessagePreview(m));
98
+ let reason = `You have ${messageCount} unread relay message(s) in ${inboxPath}.\n\n`;
99
+ reason += 'Messages:\n';
100
+ reason += previews.map(p => ` - ${p}`).join('\n');
101
+ if (messages.length > 3) {
102
+ reason += `\n ... and ${messages.length - 3} more`;
103
+ }
104
+ reason += '\n\nPlease read the inbox file and respond to all messages before stopping.';
105
+ return reason;
106
+ }
107
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/inbox-check/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Agent Relay Hooks
3
+ *
4
+ * Entry point for the hooks system types and utilities.
5
+ */
6
+ export * from './types.js';
7
+ export * from './registry.js';
8
+ export * from './trajectory-hooks.js';
9
+ export * from './emitter.js';
10
+ export * from './inbox-check/index.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Agent Relay Hooks
3
+ *
4
+ * Entry point for the hooks system types and utilities.
5
+ */
6
+ export * from './types.js';
7
+ export * from './registry.js';
8
+ export * from './trajectory-hooks.js';
9
+ export * from './emitter.js';
10
+ export * from './inbox-check/index.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC"}