hiloop-openclaw 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.
- package/dist/index.d.ts +32 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/src/api-client.d.ts +73 -0
- package/dist/src/api-client.js +69 -0
- package/dist/src/api-client.js.map +1 -0
- package/dist/src/channel.d.ts +52 -0
- package/dist/src/channel.js +168 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/config.d.ts +21 -0
- package/dist/src/config.js +23 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/tools.d.ts +12 -0
- package/dist/src/tools.js +197 -0
- package/dist/src/tools.js.map +1 -0
- package/package.json +56 -0
- package/src/skill.md +49 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HiloopChannelMonitor, HiloopChannelSender, type Gateway } from "./src/channel.js";
|
|
2
|
+
import { type ToolRegistrar } from "./src/tools.js";
|
|
3
|
+
export type { HiloopConfig } from "./src/config.js";
|
|
4
|
+
export { HiloopConfigSchema } from "./src/config.js";
|
|
5
|
+
export { HiloopApiClient } from "./src/api-client.js";
|
|
6
|
+
export { HiloopChannelMonitor, HiloopChannelSender, } from "./src/channel.js";
|
|
7
|
+
export { registerHiloopTools } from "./src/tools.js";
|
|
8
|
+
export interface PluginContext {
|
|
9
|
+
config: {
|
|
10
|
+
channels: {
|
|
11
|
+
hiloop?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
gateway: Gateway & ToolRegistrar;
|
|
15
|
+
logger: {
|
|
16
|
+
info(msg: string, ...args: unknown[]): void;
|
|
17
|
+
warn(msg: string, ...args: unknown[]): void;
|
|
18
|
+
error(msg: string, ...args: unknown[]): void;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* OpenClaw plugin entry point.
|
|
23
|
+
*
|
|
24
|
+
* Called by the OpenClaw runtime when this plugin is loaded.
|
|
25
|
+
* Reads config from `context.config.channels.hiloop`, sets up
|
|
26
|
+
* the channel monitor (inbound), sender (outbound), and tools.
|
|
27
|
+
*/
|
|
28
|
+
export declare function initialize(context: PluginContext): {
|
|
29
|
+
monitor: HiloopChannelMonitor;
|
|
30
|
+
sender: HiloopChannelSender;
|
|
31
|
+
shutdown: () => void;
|
|
32
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { HiloopConfigSchema } from "./src/config.js";
|
|
2
|
+
import { HiloopApiClient } from "./src/api-client.js";
|
|
3
|
+
import { HiloopChannelMonitor, HiloopChannelSender, } from "./src/channel.js";
|
|
4
|
+
import { registerHiloopTools } from "./src/tools.js";
|
|
5
|
+
export { HiloopConfigSchema } from "./src/config.js";
|
|
6
|
+
export { HiloopApiClient } from "./src/api-client.js";
|
|
7
|
+
export { HiloopChannelMonitor, HiloopChannelSender, } from "./src/channel.js";
|
|
8
|
+
export { registerHiloopTools } from "./src/tools.js";
|
|
9
|
+
/**
|
|
10
|
+
* OpenClaw plugin entry point.
|
|
11
|
+
*
|
|
12
|
+
* Called by the OpenClaw runtime when this plugin is loaded.
|
|
13
|
+
* Reads config from `context.config.channels.hiloop`, sets up
|
|
14
|
+
* the channel monitor (inbound), sender (outbound), and tools.
|
|
15
|
+
*/
|
|
16
|
+
export function initialize(context) {
|
|
17
|
+
const rawConfig = context.config.channels.hiloop;
|
|
18
|
+
if (!rawConfig) {
|
|
19
|
+
throw new Error("[hiloop] Missing channel config. Add channels.hiloop to your openclaw.json.");
|
|
20
|
+
}
|
|
21
|
+
const config = HiloopConfigSchema.parse(rawConfig);
|
|
22
|
+
const client = new HiloopApiClient(config);
|
|
23
|
+
// Set up channel monitor (human -> OpenClaw)
|
|
24
|
+
const monitor = new HiloopChannelMonitor(client, config, context.gateway);
|
|
25
|
+
// Set up channel sender (OpenClaw -> human)
|
|
26
|
+
const sender = new HiloopChannelSender(client, config);
|
|
27
|
+
// Register Hiloop-specific tools
|
|
28
|
+
registerHiloopTools(context.gateway, client, config);
|
|
29
|
+
// Start polling for inbound messages
|
|
30
|
+
monitor.start();
|
|
31
|
+
context.logger.info(`[hiloop] Channel active, polling every ${config.pollIntervalMs}ms`);
|
|
32
|
+
return {
|
|
33
|
+
monitor,
|
|
34
|
+
sender,
|
|
35
|
+
shutdown: () => {
|
|
36
|
+
monitor.stop();
|
|
37
|
+
context.logger.info("[hiloop] Channel stopped");
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAqB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GAEpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAsB,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAiBrD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,OAAsB;IAK/C,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAiB,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAE3C,6CAA6C;IAC7C,MAAM,OAAO,GAAG,IAAI,oBAAoB,CACtC,MAAM,EACN,MAAM,EACN,OAAO,CAAC,OAAO,CAChB,CAAC;IAEF,4CAA4C;IAC5C,MAAM,MAAM,GAAG,IAAI,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEvD,iCAAiC;IACjC,mBAAmB,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD,qCAAqC;IACrC,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO,CAAC,MAAM,CAAC,IAAI,CACjB,0CAA0C,MAAM,CAAC,cAAc,IAAI,CACpE,CAAC;IAEF,OAAO;QACL,OAAO;QACP,MAAM;QACN,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { HiloopConfig } from "./config.js";
|
|
2
|
+
export interface CreateInteractionParams {
|
|
3
|
+
type: "approval" | "chat" | "review" | "form" | "notification" | "live_session" | "voice_call" | "payment" | "scheduled_call";
|
|
4
|
+
encryptedTitle: string;
|
|
5
|
+
encryptedDescription?: string;
|
|
6
|
+
priority?: "critical" | "high" | "normal" | "low";
|
|
7
|
+
deadlineMinutes?: number;
|
|
8
|
+
encryptedOptions?: string;
|
|
9
|
+
encryptedFormSchema?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Interaction {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
status: string;
|
|
15
|
+
priority: string;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
encryptedTitle?: string;
|
|
19
|
+
encryptedDescription?: string;
|
|
20
|
+
encryptedOptions?: string;
|
|
21
|
+
encryptedResponse?: string;
|
|
22
|
+
respondedBy?: string;
|
|
23
|
+
respondedAt?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Message {
|
|
26
|
+
id: string;
|
|
27
|
+
interactionId: string;
|
|
28
|
+
sender: "agent" | "human";
|
|
29
|
+
encryptedContent: string;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
senderName?: string;
|
|
32
|
+
senderId?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface InteractionListResponse {
|
|
35
|
+
interactions: Interaction[];
|
|
36
|
+
total: number;
|
|
37
|
+
page: number;
|
|
38
|
+
pageSize: number;
|
|
39
|
+
}
|
|
40
|
+
export interface MessageListResponse {
|
|
41
|
+
messages: Message[];
|
|
42
|
+
total: number;
|
|
43
|
+
page: number;
|
|
44
|
+
pageSize: number;
|
|
45
|
+
}
|
|
46
|
+
export interface QuotaResponse {
|
|
47
|
+
used: number;
|
|
48
|
+
limit: number;
|
|
49
|
+
resetsAt: string;
|
|
50
|
+
plan: string;
|
|
51
|
+
}
|
|
52
|
+
export declare class HiloopApiClient {
|
|
53
|
+
private baseUrl;
|
|
54
|
+
private apiKey;
|
|
55
|
+
constructor(config: HiloopConfig);
|
|
56
|
+
private apiFetch;
|
|
57
|
+
createInteraction(params: CreateInteractionParams): Promise<Interaction>;
|
|
58
|
+
getInteraction(id: string): Promise<Interaction>;
|
|
59
|
+
awaitResponse(id: string, timeout?: number): Promise<Interaction>;
|
|
60
|
+
listInteractions(filters?: {
|
|
61
|
+
status?: string;
|
|
62
|
+
type?: string;
|
|
63
|
+
page?: number;
|
|
64
|
+
}): Promise<InteractionListResponse>;
|
|
65
|
+
cancelInteraction(id: string): Promise<Interaction>;
|
|
66
|
+
acknowledgeInteraction(id: string): Promise<Interaction>;
|
|
67
|
+
sendMessage(interactionId: string, content: string): Promise<Message>;
|
|
68
|
+
listMessages(interactionId: string, page?: number): Promise<MessageListResponse>;
|
|
69
|
+
checkQuota(): Promise<QuotaResponse>;
|
|
70
|
+
getTransitions(id: string): Promise<{
|
|
71
|
+
transitions: unknown[];
|
|
72
|
+
}>;
|
|
73
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export class HiloopApiClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
apiKey;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
6
|
+
this.apiKey = config.apiKey;
|
|
7
|
+
}
|
|
8
|
+
async apiFetch(path, options = {}) {
|
|
9
|
+
const url = `${this.baseUrl}/v1${path}`;
|
|
10
|
+
const headers = {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
"X-API-Key": this.apiKey,
|
|
13
|
+
...options.headers,
|
|
14
|
+
};
|
|
15
|
+
const res = await fetch(url, { ...options, headers });
|
|
16
|
+
const body = await res.json();
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
throw new Error(`Hiloop API error ${res.status}: ${body.error || JSON.stringify(body)}`);
|
|
19
|
+
}
|
|
20
|
+
return body;
|
|
21
|
+
}
|
|
22
|
+
async createInteraction(params) {
|
|
23
|
+
return this.apiFetch("/agent/interactions", {
|
|
24
|
+
method: "POST",
|
|
25
|
+
body: JSON.stringify(params),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async getInteraction(id) {
|
|
29
|
+
return this.apiFetch(`/agent/interactions/${id}`);
|
|
30
|
+
}
|
|
31
|
+
async awaitResponse(id, timeout = 30) {
|
|
32
|
+
return this.apiFetch(`/agent/interactions/${id}/await?timeout=${timeout}`);
|
|
33
|
+
}
|
|
34
|
+
async listInteractions(filters) {
|
|
35
|
+
const query = new URLSearchParams();
|
|
36
|
+
if (filters?.status)
|
|
37
|
+
query.set("status", filters.status);
|
|
38
|
+
if (filters?.type)
|
|
39
|
+
query.set("type", filters.type);
|
|
40
|
+
if (filters?.page)
|
|
41
|
+
query.set("page", String(filters.page));
|
|
42
|
+
const qs = query.toString();
|
|
43
|
+
return this.apiFetch(`/agent/interactions${qs ? `?${qs}` : ""}`);
|
|
44
|
+
}
|
|
45
|
+
async cancelInteraction(id) {
|
|
46
|
+
return this.apiFetch(`/agent/interactions/${id}`, {
|
|
47
|
+
method: "DELETE",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async acknowledgeInteraction(id) {
|
|
51
|
+
return this.apiFetch(`/agent/interactions/${id}/acknowledge`, { method: "POST" });
|
|
52
|
+
}
|
|
53
|
+
async sendMessage(interactionId, content) {
|
|
54
|
+
return this.apiFetch(`/agent/interactions/${interactionId}/messages`, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
body: JSON.stringify({ encryptedContent: content }),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async listMessages(interactionId, page = 1) {
|
|
60
|
+
return this.apiFetch(`/agent/interactions/${interactionId}/messages?page=${page}`);
|
|
61
|
+
}
|
|
62
|
+
async checkQuota() {
|
|
63
|
+
return this.apiFetch("/agent/quota");
|
|
64
|
+
}
|
|
65
|
+
async getTransitions(id) {
|
|
66
|
+
return this.apiFetch(`/agent/interactions/${id}/transitions`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HiloopApiClient } from "./api-client.js";
|
|
2
|
+
import type { HiloopConfig } from "./config.js";
|
|
3
|
+
export interface MessageEnvelope {
|
|
4
|
+
channel: string;
|
|
5
|
+
chatType: "dm" | "group";
|
|
6
|
+
sender: {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
content: string;
|
|
11
|
+
threadId: string;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
metadata?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface ChannelStatusReport {
|
|
16
|
+
connected: boolean;
|
|
17
|
+
channel: string;
|
|
18
|
+
account?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
quotaUsed?: number;
|
|
21
|
+
quotaLimit?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface Gateway {
|
|
24
|
+
handleChannelMessage(envelope: MessageEnvelope): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare class HiloopChannelMonitor {
|
|
27
|
+
private client;
|
|
28
|
+
private config;
|
|
29
|
+
private gateway;
|
|
30
|
+
private deliveredInteractions;
|
|
31
|
+
private lastMessageIds;
|
|
32
|
+
private pollTimer;
|
|
33
|
+
constructor(client: HiloopApiClient, config: HiloopConfig, gateway: Gateway);
|
|
34
|
+
start(): void;
|
|
35
|
+
stop(): void;
|
|
36
|
+
private poll;
|
|
37
|
+
private deliverInteraction;
|
|
38
|
+
private checkNewMessages;
|
|
39
|
+
private filterNewMessages;
|
|
40
|
+
}
|
|
41
|
+
export declare class HiloopChannelSender {
|
|
42
|
+
private client;
|
|
43
|
+
private config;
|
|
44
|
+
private threadToInteraction;
|
|
45
|
+
constructor(client: HiloopApiClient, config: HiloopConfig);
|
|
46
|
+
/** Map an existing thread to a Hiloop interaction */
|
|
47
|
+
trackThread(threadId: string, interactionId: string): void;
|
|
48
|
+
send(threadId: string, content: string): Promise<{
|
|
49
|
+
interactionId: string;
|
|
50
|
+
}>;
|
|
51
|
+
getStatus(): Promise<ChannelStatusReport>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export class HiloopChannelMonitor {
|
|
2
|
+
client;
|
|
3
|
+
config;
|
|
4
|
+
gateway;
|
|
5
|
+
deliveredInteractions = new Set();
|
|
6
|
+
lastMessageIds = new Map();
|
|
7
|
+
pollTimer = null;
|
|
8
|
+
constructor(client, config, gateway) {
|
|
9
|
+
this.client = client;
|
|
10
|
+
this.config = config;
|
|
11
|
+
this.gateway = gateway;
|
|
12
|
+
}
|
|
13
|
+
start() {
|
|
14
|
+
if (this.pollTimer)
|
|
15
|
+
return;
|
|
16
|
+
this.pollTimer = setInterval(() => void this.poll(), this.config.pollIntervalMs);
|
|
17
|
+
// Run an immediate first poll
|
|
18
|
+
void this.poll();
|
|
19
|
+
}
|
|
20
|
+
stop() {
|
|
21
|
+
if (this.pollTimer) {
|
|
22
|
+
clearInterval(this.pollTimer);
|
|
23
|
+
this.pollTimer = null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async poll() {
|
|
27
|
+
try {
|
|
28
|
+
// Check for responded interactions
|
|
29
|
+
const { interactions } = await this.client.listInteractions({
|
|
30
|
+
status: "responded",
|
|
31
|
+
});
|
|
32
|
+
for (const interaction of interactions) {
|
|
33
|
+
if (!this.deliveredInteractions.has(interaction.id)) {
|
|
34
|
+
await this.deliverInteraction(interaction);
|
|
35
|
+
this.deliveredInteractions.add(interaction.id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Check for new messages on active chat interactions
|
|
39
|
+
const activeChats = await this.client.listInteractions({
|
|
40
|
+
status: "assigned",
|
|
41
|
+
type: "chat",
|
|
42
|
+
});
|
|
43
|
+
for (const chat of activeChats.interactions) {
|
|
44
|
+
await this.checkNewMessages(chat);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error("[hiloop] Poll error:", err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async deliverInteraction(interaction) {
|
|
52
|
+
// For chat interactions, deliver the latest messages
|
|
53
|
+
if (interaction.type === "chat") {
|
|
54
|
+
await this.checkNewMessages(interaction);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// For other types (approval, review, form, etc.), deliver the response
|
|
58
|
+
const envelope = {
|
|
59
|
+
channel: "hiloop",
|
|
60
|
+
chatType: "dm",
|
|
61
|
+
sender: {
|
|
62
|
+
id: interaction.respondedBy || "unknown",
|
|
63
|
+
name: interaction.respondedBy || "Human",
|
|
64
|
+
},
|
|
65
|
+
content: interaction.encryptedResponse || "[responded]",
|
|
66
|
+
threadId: interaction.id,
|
|
67
|
+
timestamp: interaction.respondedAt || interaction.updatedAt,
|
|
68
|
+
metadata: {
|
|
69
|
+
interactionType: interaction.type,
|
|
70
|
+
status: interaction.status,
|
|
71
|
+
priority: interaction.priority,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
await this.gateway.handleChannelMessage(envelope);
|
|
75
|
+
}
|
|
76
|
+
async checkNewMessages(interaction) {
|
|
77
|
+
try {
|
|
78
|
+
const { messages } = await this.client.listMessages(interaction.id);
|
|
79
|
+
const lastKnown = this.lastMessageIds.get(interaction.id);
|
|
80
|
+
const newMessages = this.filterNewMessages(messages, lastKnown);
|
|
81
|
+
for (const msg of newMessages) {
|
|
82
|
+
if (msg.sender === "human") {
|
|
83
|
+
const envelope = {
|
|
84
|
+
channel: "hiloop",
|
|
85
|
+
chatType: "dm",
|
|
86
|
+
sender: {
|
|
87
|
+
id: msg.senderId || "unknown",
|
|
88
|
+
name: msg.senderName || "Human",
|
|
89
|
+
},
|
|
90
|
+
content: msg.encryptedContent,
|
|
91
|
+
threadId: interaction.id,
|
|
92
|
+
timestamp: msg.createdAt,
|
|
93
|
+
metadata: {
|
|
94
|
+
messageId: msg.id,
|
|
95
|
+
interactionType: interaction.type,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
await this.gateway.handleChannelMessage(envelope);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (messages.length > 0) {
|
|
102
|
+
this.lastMessageIds.set(interaction.id, messages[messages.length - 1].id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
console.error(`[hiloop] Error checking messages for ${interaction.id}:`, err);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
filterNewMessages(messages, lastKnownId) {
|
|
110
|
+
if (!lastKnownId)
|
|
111
|
+
return messages;
|
|
112
|
+
const idx = messages.findIndex((m) => m.id === lastKnownId);
|
|
113
|
+
if (idx === -1)
|
|
114
|
+
return messages;
|
|
115
|
+
return messages.slice(idx + 1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export class HiloopChannelSender {
|
|
119
|
+
client;
|
|
120
|
+
config;
|
|
121
|
+
// Maps OpenClaw threadId -> Hiloop interactionId
|
|
122
|
+
threadToInteraction = new Map();
|
|
123
|
+
constructor(client, config) {
|
|
124
|
+
this.client = client;
|
|
125
|
+
this.config = config;
|
|
126
|
+
}
|
|
127
|
+
/** Map an existing thread to a Hiloop interaction */
|
|
128
|
+
trackThread(threadId, interactionId) {
|
|
129
|
+
this.threadToInteraction.set(threadId, interactionId);
|
|
130
|
+
}
|
|
131
|
+
async send(threadId, content) {
|
|
132
|
+
const existingId = this.threadToInteraction.get(threadId);
|
|
133
|
+
if (existingId) {
|
|
134
|
+
// Send a message on the existing interaction
|
|
135
|
+
await this.client.sendMessage(existingId, content);
|
|
136
|
+
return { interactionId: existingId };
|
|
137
|
+
}
|
|
138
|
+
// Create a new chat interaction
|
|
139
|
+
const interaction = await this.client.createInteraction({
|
|
140
|
+
type: "chat",
|
|
141
|
+
encryptedTitle: content.slice(0, 100),
|
|
142
|
+
encryptedDescription: content,
|
|
143
|
+
priority: this.config.defaultPriority,
|
|
144
|
+
});
|
|
145
|
+
this.threadToInteraction.set(threadId, interaction.id);
|
|
146
|
+
return { interactionId: interaction.id };
|
|
147
|
+
}
|
|
148
|
+
async getStatus() {
|
|
149
|
+
try {
|
|
150
|
+
const quota = await this.client.checkQuota();
|
|
151
|
+
return {
|
|
152
|
+
connected: true,
|
|
153
|
+
channel: "hiloop",
|
|
154
|
+
account: quota.plan,
|
|
155
|
+
quotaUsed: quota.used,
|
|
156
|
+
quotaLimit: quota.limit,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
return {
|
|
161
|
+
connected: false,
|
|
162
|
+
channel: "hiloop",
|
|
163
|
+
error: err instanceof Error ? err.message : String(err),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const HiloopConfigSchema: z.ZodObject<{
|
|
3
|
+
apiKey: z.ZodString;
|
|
4
|
+
baseUrl: z.ZodDefault<z.ZodString>;
|
|
5
|
+
pollIntervalMs: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
defaultPriority: z.ZodDefault<z.ZodEnum<["critical", "high", "normal", "low"]>>;
|
|
7
|
+
dmPolicy: z.ZodDefault<z.ZodEnum<["pairing", "allowlist", "open"]>>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
apiKey: string;
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
pollIntervalMs: number;
|
|
12
|
+
defaultPriority: "critical" | "high" | "normal" | "low";
|
|
13
|
+
dmPolicy: "pairing" | "allowlist" | "open";
|
|
14
|
+
}, {
|
|
15
|
+
apiKey: string;
|
|
16
|
+
baseUrl?: string | undefined;
|
|
17
|
+
pollIntervalMs?: number | undefined;
|
|
18
|
+
defaultPriority?: "critical" | "high" | "normal" | "low" | undefined;
|
|
19
|
+
dmPolicy?: "pairing" | "allowlist" | "open" | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
export type HiloopConfig = z.infer<typeof HiloopConfigSchema>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const HiloopConfigSchema = z.object({
|
|
3
|
+
apiKey: z
|
|
4
|
+
.string()
|
|
5
|
+
.startsWith("hlp_", "API key must start with hlp_"),
|
|
6
|
+
baseUrl: z
|
|
7
|
+
.string()
|
|
8
|
+
.url()
|
|
9
|
+
.default("https://api.hi-loop.com"),
|
|
10
|
+
pollIntervalMs: z
|
|
11
|
+
.number()
|
|
12
|
+
.int()
|
|
13
|
+
.min(500)
|
|
14
|
+
.max(30_000)
|
|
15
|
+
.default(2000),
|
|
16
|
+
defaultPriority: z
|
|
17
|
+
.enum(["critical", "high", "normal", "low"])
|
|
18
|
+
.default("normal"),
|
|
19
|
+
dmPolicy: z
|
|
20
|
+
.enum(["pairing", "allowlist", "open"])
|
|
21
|
+
.default("pairing"),
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,UAAU,CAAC,MAAM,EAAE,8BAA8B,CAAC;IACrD,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,yBAAyB,CAAC;IACrC,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,GAAG,CAAC;SACR,GAAG,CAAC,MAAM,CAAC;SACX,OAAO,CAAC,IAAI,CAAC;IAChB,eAAe,EAAE,CAAC;SACf,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;SAC3C,OAAO,CAAC,QAAQ,CAAC;IACpB,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;SACtC,OAAO,CAAC,SAAS,CAAC;CACtB,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { HiloopApiClient } from "./api-client.js";
|
|
3
|
+
import type { HiloopConfig } from "./config.js";
|
|
4
|
+
export interface ToolRegistrar {
|
|
5
|
+
registerTool(def: {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
schema: z.ZodObject<z.ZodRawShape>;
|
|
9
|
+
handler: (params: Record<string, unknown>) => Promise<unknown>;
|
|
10
|
+
}): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function registerHiloopTools(registrar: ToolRegistrar, client: HiloopApiClient, config: HiloopConfig): void;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerHiloopTools(registrar, client, config) {
|
|
3
|
+
registrar.registerTool({
|
|
4
|
+
name: "hiloop_request_approval",
|
|
5
|
+
description: "Request approval from a human via Hiloop. Use when you need permission " +
|
|
6
|
+
"to proceed with a dangerous or irreversible action.",
|
|
7
|
+
schema: z.object({
|
|
8
|
+
title: z.string().describe("What you need approved"),
|
|
9
|
+
options: z
|
|
10
|
+
.array(z.string())
|
|
11
|
+
.default(["Approve", "Deny"])
|
|
12
|
+
.describe("Choices for the human (default: Approve/Deny)"),
|
|
13
|
+
priority: z
|
|
14
|
+
.enum(["critical", "high", "normal", "low"])
|
|
15
|
+
.default(config.defaultPriority)
|
|
16
|
+
.describe("Priority level"),
|
|
17
|
+
deadlineMinutes: z
|
|
18
|
+
.number()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Deadline in minutes from now"),
|
|
21
|
+
description: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Additional context for the human"),
|
|
25
|
+
}),
|
|
26
|
+
handler: async (params) => {
|
|
27
|
+
const interaction = await client.createInteraction({
|
|
28
|
+
type: "approval",
|
|
29
|
+
encryptedTitle: params.title,
|
|
30
|
+
encryptedDescription: params.description,
|
|
31
|
+
encryptedOptions: JSON.stringify(params.options),
|
|
32
|
+
priority: params.priority || config.defaultPriority,
|
|
33
|
+
deadlineMinutes: params.deadlineMinutes,
|
|
34
|
+
});
|
|
35
|
+
return { interactionId: interaction.id, status: interaction.status };
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
registrar.registerTool({
|
|
39
|
+
name: "hiloop_request_review",
|
|
40
|
+
description: "Request a human review of content, code, or a document via Hiloop.",
|
|
41
|
+
schema: z.object({
|
|
42
|
+
title: z.string().describe("What needs to be reviewed"),
|
|
43
|
+
description: z
|
|
44
|
+
.string()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Content or details to review"),
|
|
47
|
+
priority: z
|
|
48
|
+
.enum(["critical", "high", "normal", "low"])
|
|
49
|
+
.default(config.defaultPriority),
|
|
50
|
+
deadlineMinutes: z.number().optional(),
|
|
51
|
+
}),
|
|
52
|
+
handler: async (params) => {
|
|
53
|
+
const interaction = await client.createInteraction({
|
|
54
|
+
type: "review",
|
|
55
|
+
encryptedTitle: params.title,
|
|
56
|
+
encryptedDescription: params.description,
|
|
57
|
+
priority: params.priority || config.defaultPriority,
|
|
58
|
+
deadlineMinutes: params.deadlineMinutes,
|
|
59
|
+
});
|
|
60
|
+
return { interactionId: interaction.id, status: interaction.status };
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
registrar.registerTool({
|
|
64
|
+
name: "hiloop_request_form",
|
|
65
|
+
description: "Send a form to a human to fill out. Useful for gathering structured data.",
|
|
66
|
+
schema: z.object({
|
|
67
|
+
title: z.string().describe("Form title"),
|
|
68
|
+
formSchema: z
|
|
69
|
+
.string()
|
|
70
|
+
.describe("JSON schema describing the form fields"),
|
|
71
|
+
priority: z
|
|
72
|
+
.enum(["critical", "high", "normal", "low"])
|
|
73
|
+
.default(config.defaultPriority),
|
|
74
|
+
deadlineMinutes: z.number().optional(),
|
|
75
|
+
}),
|
|
76
|
+
handler: async (params) => {
|
|
77
|
+
const interaction = await client.createInteraction({
|
|
78
|
+
type: "form",
|
|
79
|
+
encryptedTitle: params.title,
|
|
80
|
+
encryptedFormSchema: params.formSchema,
|
|
81
|
+
priority: params.priority || config.defaultPriority,
|
|
82
|
+
deadlineMinutes: params.deadlineMinutes,
|
|
83
|
+
});
|
|
84
|
+
return { interactionId: interaction.id, status: interaction.status };
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
registrar.registerTool({
|
|
88
|
+
name: "hiloop_send_notification",
|
|
89
|
+
description: "Send a fire-and-forget notification to a human. No response expected.",
|
|
90
|
+
schema: z.object({
|
|
91
|
+
title: z.string().describe("Notification title"),
|
|
92
|
+
description: z
|
|
93
|
+
.string()
|
|
94
|
+
.optional()
|
|
95
|
+
.describe("Notification body"),
|
|
96
|
+
priority: z
|
|
97
|
+
.enum(["critical", "high", "normal", "low"])
|
|
98
|
+
.default(config.defaultPriority),
|
|
99
|
+
}),
|
|
100
|
+
handler: async (params) => {
|
|
101
|
+
const interaction = await client.createInteraction({
|
|
102
|
+
type: "notification",
|
|
103
|
+
encryptedTitle: params.title,
|
|
104
|
+
encryptedDescription: params.description,
|
|
105
|
+
priority: params.priority || config.defaultPriority,
|
|
106
|
+
});
|
|
107
|
+
return { interactionId: interaction.id, status: interaction.status };
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
registrar.registerTool({
|
|
111
|
+
name: "hiloop_start_live_session",
|
|
112
|
+
description: "Start a live session with a human for real-time screen sharing or collaboration.",
|
|
113
|
+
schema: z.object({
|
|
114
|
+
title: z.string().describe("Session title"),
|
|
115
|
+
description: z
|
|
116
|
+
.string()
|
|
117
|
+
.optional()
|
|
118
|
+
.describe("What the session is about"),
|
|
119
|
+
priority: z
|
|
120
|
+
.enum(["critical", "high", "normal", "low"])
|
|
121
|
+
.default(config.defaultPriority),
|
|
122
|
+
}),
|
|
123
|
+
handler: async (params) => {
|
|
124
|
+
const interaction = await client.createInteraction({
|
|
125
|
+
type: "live_session",
|
|
126
|
+
encryptedTitle: params.title,
|
|
127
|
+
encryptedDescription: params.description,
|
|
128
|
+
priority: params.priority || config.defaultPriority,
|
|
129
|
+
});
|
|
130
|
+
return { interactionId: interaction.id, status: interaction.status };
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
registrar.registerTool({
|
|
134
|
+
name: "hiloop_check_status",
|
|
135
|
+
description: "Check the current status of a Hiloop interaction.",
|
|
136
|
+
schema: z.object({
|
|
137
|
+
interactionId: z.string().describe("The interaction ID to check"),
|
|
138
|
+
}),
|
|
139
|
+
handler: async (params) => {
|
|
140
|
+
const interaction = await client.getInteraction(params.interactionId);
|
|
141
|
+
return {
|
|
142
|
+
id: interaction.id,
|
|
143
|
+
type: interaction.type,
|
|
144
|
+
status: interaction.status,
|
|
145
|
+
priority: interaction.priority,
|
|
146
|
+
respondedBy: interaction.respondedBy,
|
|
147
|
+
respondedAt: interaction.respondedAt,
|
|
148
|
+
encryptedResponse: interaction.encryptedResponse,
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
registrar.registerTool({
|
|
153
|
+
name: "hiloop_await_response",
|
|
154
|
+
description: "Wait for a human to respond to a Hiloop interaction. Long-polls up to 30 seconds.",
|
|
155
|
+
schema: z.object({
|
|
156
|
+
interactionId: z.string().describe("The interaction ID to wait on"),
|
|
157
|
+
timeout: z
|
|
158
|
+
.number()
|
|
159
|
+
.min(1)
|
|
160
|
+
.max(30)
|
|
161
|
+
.default(30)
|
|
162
|
+
.describe("Timeout in seconds (max 30)"),
|
|
163
|
+
}),
|
|
164
|
+
handler: async (params) => {
|
|
165
|
+
const interaction = await client.awaitResponse(params.interactionId, params.timeout);
|
|
166
|
+
return {
|
|
167
|
+
id: interaction.id,
|
|
168
|
+
status: interaction.status,
|
|
169
|
+
encryptedResponse: interaction.encryptedResponse,
|
|
170
|
+
respondedBy: interaction.respondedBy,
|
|
171
|
+
respondedAt: interaction.respondedAt,
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
registrar.registerTool({
|
|
176
|
+
name: "hiloop_cancel_request",
|
|
177
|
+
description: "Cancel a pending Hiloop interaction.",
|
|
178
|
+
schema: z.object({
|
|
179
|
+
interactionId: z
|
|
180
|
+
.string()
|
|
181
|
+
.describe("The interaction ID to cancel"),
|
|
182
|
+
}),
|
|
183
|
+
handler: async (params) => {
|
|
184
|
+
const interaction = await client.cancelInteraction(params.interactionId);
|
|
185
|
+
return { id: interaction.id, status: interaction.status };
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
registrar.registerTool({
|
|
189
|
+
name: "hiloop_check_quota",
|
|
190
|
+
description: "Check your Hiloop usage quota (how many interactions you can create).",
|
|
191
|
+
schema: z.object({}),
|
|
192
|
+
handler: async () => {
|
|
193
|
+
return await client.checkQuota();
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hiloop-openclaw",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hiloop channel plugin for OpenClaw - human-in-the-loop for AI agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src/skill.md"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"prepublishOnly": "tsc",
|
|
15
|
+
"dev": "tsc --watch"
|
|
16
|
+
},
|
|
17
|
+
"openclaw": {
|
|
18
|
+
"extensions": ["channel", "tools"],
|
|
19
|
+
"channel": {
|
|
20
|
+
"id": "hiloop",
|
|
21
|
+
"label": "Hiloop",
|
|
22
|
+
"description": "Human-in-the-loop interactions: approvals, chat, reviews, forms, live sessions, voice"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/sjorsdev/hiloop.git",
|
|
28
|
+
"directory": "integrations/openclaw"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://www.hi-loop.com/docs/openclaw",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/sjorsdev/hiloop/issues"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"openclaw",
|
|
36
|
+
"openclaw-plugin",
|
|
37
|
+
"openclaw-channel",
|
|
38
|
+
"hiloop",
|
|
39
|
+
"human-in-the-loop",
|
|
40
|
+
"ai-agents",
|
|
41
|
+
"approval",
|
|
42
|
+
"review",
|
|
43
|
+
"chat"
|
|
44
|
+
],
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"zod": "^3.24"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^22",
|
|
54
|
+
"typescript": "^5.7"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/skill.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Hiloop - Human-in-the-Loop Channel
|
|
2
|
+
|
|
3
|
+
You have access to Hiloop, a zero-trust human-in-the-loop platform. Use it to reach humans for approvals, reviews, chat, forms, live sessions, and notifications.
|
|
4
|
+
|
|
5
|
+
## When to use Hiloop
|
|
6
|
+
|
|
7
|
+
- **Approvals**: Use `hiloop_request_approval` when you need permission to do something dangerous, irreversible, or costly. Examples: deploying to production, deleting data, spending money, sending emails.
|
|
8
|
+
- **Reviews**: Use `hiloop_request_review` when you need a human to review content, code, or a document before proceeding.
|
|
9
|
+
- **Forms**: Use `hiloop_request_form` when you need structured data from a human (e.g., configuration, preferences, details for a task).
|
|
10
|
+
- **Notifications**: Use `hiloop_send_notification` for fire-and-forget updates. No response expected.
|
|
11
|
+
- **Live sessions**: Use `hiloop_start_live_session` when you need real-time collaboration or screen sharing.
|
|
12
|
+
- **Chat**: Send messages through the Hiloop channel for conversational back-and-forth.
|
|
13
|
+
|
|
14
|
+
## Priority guide
|
|
15
|
+
|
|
16
|
+
- `critical` - Blocking, time-sensitive, needs immediate attention
|
|
17
|
+
- `high` - Important, should be handled soon
|
|
18
|
+
- `normal` - Default, handled in regular order
|
|
19
|
+
- `low` - Can wait, non-urgent
|
|
20
|
+
|
|
21
|
+
## Workflow patterns
|
|
22
|
+
|
|
23
|
+
### Approval gate
|
|
24
|
+
```
|
|
25
|
+
1. hiloop_request_approval(title: "Deploy v2.3 to production", options: ["Approve", "Deny", "Defer"])
|
|
26
|
+
2. hiloop_await_response(interactionId: "...")
|
|
27
|
+
3. If approved, proceed. If denied, stop. If deferred, wait and check later.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Gather information
|
|
31
|
+
```
|
|
32
|
+
1. hiloop_request_form(title: "Database migration config", formSchema: '{"host":"string","port":"number"}')
|
|
33
|
+
2. hiloop_await_response(interactionId: "...")
|
|
34
|
+
3. Use the submitted form data to proceed.
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Notify and continue
|
|
38
|
+
```
|
|
39
|
+
1. hiloop_send_notification(title: "Build completed successfully")
|
|
40
|
+
2. Continue with next task (no need to wait).
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Tips
|
|
44
|
+
|
|
45
|
+
- Always include a clear, descriptive title so the human knows what they are responding to.
|
|
46
|
+
- Set deadlines for time-sensitive requests using `deadlineMinutes`.
|
|
47
|
+
- Use `hiloop_check_status` to poll for status without blocking.
|
|
48
|
+
- Use `hiloop_await_response` (up to 30s) for synchronous waiting.
|
|
49
|
+
- Check `hiloop_check_quota` if you are creating many interactions.
|