@cfio/cohort-sync 0.31.11 → 0.31.13
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 +148 -7
- package/dist/openclaw.plugin.json +4 -1
- package/dist/package.json +1 -1
- package/openclaw.plugin.json +4 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -11999,6 +11999,8 @@ var acknowledgeCommandRef = makeFunctionReference("gatewayCommands:acknowledgeCo
|
|
|
11999
11999
|
var failCommandRef = makeFunctionReference("gatewayCommands:failCommand");
|
|
12000
12000
|
var getChannelsForPlugin = makeFunctionReference("cloudGatewayChannels:listForPlugin");
|
|
12001
12001
|
var addCommentFromPluginRef = makeFunctionReference("comments:addCommentFromPlugin");
|
|
12002
|
+
var addRoomMessageFromPluginRef = makeFunctionReference("rooms:addMessageFromPlugin");
|
|
12003
|
+
var promptAgentsFromPluginRef = makeFunctionReference("rooms:promptAgentsFromPlugin");
|
|
12002
12004
|
var transitionFromPluginRef = makeFunctionReference("tasks:transitionFromPlugin");
|
|
12003
12005
|
async function pushTelemetry(apiKey2, data) {
|
|
12004
12006
|
if (authCircuitOpen) return;
|
|
@@ -12102,6 +12104,55 @@ async function callAddCommentFromPlugin(apiKey2, args) {
|
|
|
12102
12104
|
throw err;
|
|
12103
12105
|
}
|
|
12104
12106
|
}
|
|
12107
|
+
async function callAddRoomMessageFromPlugin(apiKey2, args) {
|
|
12108
|
+
if (authCircuitOpen) {
|
|
12109
|
+
throw new Error(
|
|
12110
|
+
'cohort-sync: API key rejected \u2014 all outbound mutations disabled until gateway restart.\n 1. Create a new key at https://my.cohort.bot/settings/api-keys\n 2. Run: openclaw config set plugins.entries.cohort-sync.config.apiKey "ch_live_..."'
|
|
12111
|
+
);
|
|
12112
|
+
}
|
|
12113
|
+
const c = getClient();
|
|
12114
|
+
if (!c) {
|
|
12115
|
+
throw new Error("Convex client not initialized \u2014 subscription may not be active");
|
|
12116
|
+
}
|
|
12117
|
+
try {
|
|
12118
|
+
return await c.mutation(addRoomMessageFromPluginRef, {
|
|
12119
|
+
apiKeyHash: hashApiKey(apiKey2),
|
|
12120
|
+
roomId: args.roomId,
|
|
12121
|
+
agentName: args.agentName,
|
|
12122
|
+
body: args.content
|
|
12123
|
+
});
|
|
12124
|
+
} catch (err) {
|
|
12125
|
+
if (isUnauthorizedError(err)) {
|
|
12126
|
+
tripAuthCircuit();
|
|
12127
|
+
}
|
|
12128
|
+
throw err;
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12131
|
+
async function callPromptRoomAgentsFromPlugin(apiKey2, args) {
|
|
12132
|
+
if (authCircuitOpen) {
|
|
12133
|
+
throw new Error(
|
|
12134
|
+
'cohort-sync: API key rejected \u2014 all outbound mutations disabled until gateway restart.\n 1. Create a new key at https://my.cohort.bot/settings/api-keys\n 2. Run: openclaw config set plugins.entries.cohort-sync.config.apiKey "ch_live_..."'
|
|
12135
|
+
);
|
|
12136
|
+
}
|
|
12137
|
+
const c = getClient();
|
|
12138
|
+
if (!c) {
|
|
12139
|
+
throw new Error("Convex client not initialized \u2014 subscription may not be active");
|
|
12140
|
+
}
|
|
12141
|
+
try {
|
|
12142
|
+
return await c.mutation(promptAgentsFromPluginRef, {
|
|
12143
|
+
apiKeyHash: hashApiKey(apiKey2),
|
|
12144
|
+
roomId: args.roomId,
|
|
12145
|
+
moderatorAgentName: args.moderatorAgentName,
|
|
12146
|
+
targetAgentNames: args.targetAgentNames,
|
|
12147
|
+
prompt: args.prompt
|
|
12148
|
+
});
|
|
12149
|
+
} catch (err) {
|
|
12150
|
+
if (isUnauthorizedError(err)) {
|
|
12151
|
+
tripAuthCircuit();
|
|
12152
|
+
}
|
|
12153
|
+
throw err;
|
|
12154
|
+
}
|
|
12155
|
+
}
|
|
12105
12156
|
async function callTransitionFromPlugin(apiKey2, args) {
|
|
12106
12157
|
if (authCircuitOpen) {
|
|
12107
12158
|
throw new Error(
|
|
@@ -12142,6 +12193,7 @@ var ATMENTION_RESPONSE_PROMPT = `YOU WERE DIRECTLY @-MENTIONED. RESPOND.
|
|
|
12142
12193
|
var TOOLS_REFERENCE = `
|
|
12143
12194
|
TOOLS: Use these \u2014 do NOT call the REST API directly.
|
|
12144
12195
|
- cohort_comment(task_number, comment) \u2014 post a comment
|
|
12196
|
+
- cohort_room_message(room_id, message) \u2014 post a message in a Cohort Room
|
|
12145
12197
|
- cohort_task(task_number) \u2014 fetch full task details + comments
|
|
12146
12198
|
- cohort_transition(task_number, status) \u2014 change status
|
|
12147
12199
|
- cohort_assign(task_number, assignee) \u2014 assign/unassign
|
|
@@ -12153,6 +12205,11 @@ function buildNotificationMessage(n) {
|
|
|
12153
12205
|
let header;
|
|
12154
12206
|
let cta;
|
|
12155
12207
|
switch (n.type) {
|
|
12208
|
+
case "room_message":
|
|
12209
|
+
header = `New message in Room "${n.roomName ?? n.roomId ?? "Room"}"
|
|
12210
|
+
From: ${n.actorName}`;
|
|
12211
|
+
cta = `Reply in the Room if you can help. Use the cohort_room_message tool (roomId: ${n.roomId ?? "unknown"}).`;
|
|
12212
|
+
break;
|
|
12156
12213
|
case "comment":
|
|
12157
12214
|
if (n.isMentioned) {
|
|
12158
12215
|
header = `You were @mentioned on task #${n.taskNumber} "${n.taskTitle}"
|
|
@@ -12181,7 +12238,7 @@ From: ${n.actorName}`;
|
|
|
12181
12238
|
}
|
|
12182
12239
|
let body = "";
|
|
12183
12240
|
if (n.preview) {
|
|
12184
|
-
if (n.type === "comment") {
|
|
12241
|
+
if (n.type === "comment" || n.type === "room_message") {
|
|
12185
12242
|
const safe = sanitizePreview(n.preview);
|
|
12186
12243
|
body = `
|
|
12187
12244
|
<user_comment>
|
|
@@ -12200,7 +12257,7 @@ Comment: "${n.preview}"`;
|
|
|
12200
12257
|
Scope: ${truncated}`;
|
|
12201
12258
|
}
|
|
12202
12259
|
let prompt;
|
|
12203
|
-
if (n.type === "comment" && n.isMentioned) {
|
|
12260
|
+
if (n.type === "comment" && n.isMentioned || n.type === "room_message") {
|
|
12204
12261
|
prompt = n.behavioralPrompt ? `${n.behavioralPrompt}
|
|
12205
12262
|
|
|
12206
12263
|
${ATMENTION_RESPONSE_PROMPT}` : ATMENTION_RESPONSE_PROMPT;
|
|
@@ -12209,7 +12266,7 @@ ${ATMENTION_RESPONSE_PROMPT}` : ATMENTION_RESPONSE_PROMPT;
|
|
|
12209
12266
|
|
|
12210
12267
|
${DEFAULT_BEHAVIORAL_PROMPT}` : DEFAULT_BEHAVIORAL_PROMPT;
|
|
12211
12268
|
}
|
|
12212
|
-
const promptBlock = n.type === "comment" ? `
|
|
12269
|
+
const promptBlock = n.type === "comment" || n.type === "room_message" ? `
|
|
12213
12270
|
|
|
12214
12271
|
---
|
|
12215
12272
|
${prompt}` : "";
|
|
@@ -12218,6 +12275,7 @@ ${prompt}` : "";
|
|
|
12218
12275
|
${cta}${promptBlock}${TOOLS_REFERENCE}`;
|
|
12219
12276
|
}
|
|
12220
12277
|
async function injectNotification(port, hooksToken, n, agentId = "main") {
|
|
12278
|
+
const sessionKey = n.type === "room_message" && n.roomId ? `hook:cohort:room-${n.roomId}` : `hook:cohort:task-${n.taskNumber}`;
|
|
12221
12279
|
const response = await fetch(`http://localhost:${port}/hooks/agent`, {
|
|
12222
12280
|
method: "POST",
|
|
12223
12281
|
headers: {
|
|
@@ -12229,7 +12287,7 @@ async function injectNotification(port, hooksToken, n, agentId = "main") {
|
|
|
12229
12287
|
name: "Cohort",
|
|
12230
12288
|
agentId,
|
|
12231
12289
|
deliver: false,
|
|
12232
|
-
sessionKey
|
|
12290
|
+
sessionKey
|
|
12233
12291
|
}),
|
|
12234
12292
|
signal: AbortSignal.timeout(1e4)
|
|
12235
12293
|
});
|
|
@@ -12317,7 +12375,8 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
|
|
|
12317
12375
|
try {
|
|
12318
12376
|
if (hooksToken) {
|
|
12319
12377
|
await injectNotification(port, hooksToken, n, openclawAgentId);
|
|
12320
|
-
|
|
12378
|
+
const targetLabel = n.type === "room_message" ? `room ${n.roomId ?? n.roomName ?? "unknown"}` : `task #${n.taskNumber}`;
|
|
12379
|
+
logger.info(`cohort-sync: injected notification for ${targetLabel} (${agentName})`);
|
|
12321
12380
|
} else {
|
|
12322
12381
|
throw new Error(
|
|
12323
12382
|
`no transport available for notification ${n._id} (gwClient alive: ${gwClient?.isAlive() ?? "null"}, hooksToken: ${!!hooksToken})`
|
|
@@ -12332,8 +12391,9 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
|
|
|
12332
12391
|
const newFailCount = failCount + 1;
|
|
12333
12392
|
deliveryFailures.set(n._id, newFailCount);
|
|
12334
12393
|
if (newFailCount >= MAX_DELIVERY_ATTEMPTS) {
|
|
12394
|
+
const targetLabel = n.type === "room_message" ? `room ${n.roomId ?? n.roomName ?? "unknown"}` : `task #${n.taskNumber}`;
|
|
12335
12395
|
logger.error(
|
|
12336
|
-
`cohort-sync: dead-letter notification ${n._id} for
|
|
12396
|
+
`cohort-sync: dead-letter notification ${n._id} for ${targetLabel} (${n.type} from ${n.actorName}) after ${MAX_DELIVERY_ATTEMPTS} failed delivery attempts: ${String(err)}`
|
|
12337
12397
|
);
|
|
12338
12398
|
try {
|
|
12339
12399
|
await c.mutation(markDeliveredByPlugin, {
|
|
@@ -13741,7 +13801,7 @@ function dumpEvent(event) {
|
|
|
13741
13801
|
function positiveNumber(value) {
|
|
13742
13802
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
13743
13803
|
}
|
|
13744
|
-
var PLUGIN_VERSION = true ? "0.31.
|
|
13804
|
+
var PLUGIN_VERSION = true ? "0.31.13" : "unknown";
|
|
13745
13805
|
function resolveGatewayToken(api) {
|
|
13746
13806
|
const token2 = api.config?.gateway?.auth?.token;
|
|
13747
13807
|
return typeof token2 === "string" ? token2 : null;
|
|
@@ -14871,6 +14931,87 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14871
14931
|
}
|
|
14872
14932
|
};
|
|
14873
14933
|
});
|
|
14934
|
+
api.registerTool((toolCtx) => {
|
|
14935
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14936
|
+
return {
|
|
14937
|
+
name: "cohort_room_message",
|
|
14938
|
+
label: "cohort_room_message",
|
|
14939
|
+
description: "Post a message in a Cohort Room. Use this to reply when you are participating in a Room chat.",
|
|
14940
|
+
parameters: Type.Object({
|
|
14941
|
+
room_id: Type.String({ description: "Room ID supplied by Cohort, e.g. rooms:abc123" }),
|
|
14942
|
+
message: Type.String({ description: "Message text to post in the Room" })
|
|
14943
|
+
}),
|
|
14944
|
+
async execute(_toolCallId, params) {
|
|
14945
|
+
const rt = getToolRuntime();
|
|
14946
|
+
if (!rt.isReady) {
|
|
14947
|
+
return textResult("cohort_room_message is not ready yet \u2014 the plugin is still starting up. Try again in a few seconds.");
|
|
14948
|
+
}
|
|
14949
|
+
const agentName = rt.resolveAgentName(agentId);
|
|
14950
|
+
const result = await callAddRoomMessageFromPlugin(rt.apiKey, {
|
|
14951
|
+
roomId: params.room_id,
|
|
14952
|
+
agentName,
|
|
14953
|
+
content: params.message
|
|
14954
|
+
});
|
|
14955
|
+
return textResult(`Message posted to Room ${params.room_id}.`, result);
|
|
14956
|
+
}
|
|
14957
|
+
};
|
|
14958
|
+
});
|
|
14959
|
+
api.registerTool((toolCtx) => {
|
|
14960
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14961
|
+
return {
|
|
14962
|
+
name: "cohort_room_prompt_agent",
|
|
14963
|
+
label: "cohort_room_prompt_agent",
|
|
14964
|
+
description: "Ask one agent in a Cohort Room to respond. Use this when you are the Room moderator and need controlled turn-taking.",
|
|
14965
|
+
parameters: Type.Object({
|
|
14966
|
+
room_id: Type.String({ description: "Room ID supplied by Cohort, e.g. rooms:abc123" }),
|
|
14967
|
+
agent_name: Type.String({ description: "Cohort agent name to prompt, e.g. iris" }),
|
|
14968
|
+
prompt: Type.String({ description: "Prompt to send to the target agent" })
|
|
14969
|
+
}),
|
|
14970
|
+
async execute(_toolCallId, params) {
|
|
14971
|
+
const rt = getToolRuntime();
|
|
14972
|
+
if (!rt.isReady) {
|
|
14973
|
+
return textResult("cohort_room_prompt_agent is not ready yet \u2014 the plugin is still starting up. Try again in a few seconds.");
|
|
14974
|
+
}
|
|
14975
|
+
const moderatorAgentName = rt.resolveAgentName(agentId);
|
|
14976
|
+
const result = await callPromptRoomAgentsFromPlugin(rt.apiKey, {
|
|
14977
|
+
roomId: params.room_id,
|
|
14978
|
+
moderatorAgentName,
|
|
14979
|
+
targetAgentNames: [params.agent_name],
|
|
14980
|
+
prompt: params.prompt
|
|
14981
|
+
});
|
|
14982
|
+
const noun = result.notificationCount === 1 ? "agent" : "agents";
|
|
14983
|
+
return textResult(`Prompt sent to ${result.notificationCount} Room ${noun}.`, result);
|
|
14984
|
+
}
|
|
14985
|
+
};
|
|
14986
|
+
});
|
|
14987
|
+
api.registerTool((toolCtx) => {
|
|
14988
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14989
|
+
return {
|
|
14990
|
+
name: "cohort_room_prompt_agents",
|
|
14991
|
+
label: "cohort_room_prompt_agents",
|
|
14992
|
+
description: "Ask multiple agents in a Cohort Room to respond in one controlled moderator action.",
|
|
14993
|
+
parameters: Type.Object({
|
|
14994
|
+
room_id: Type.String({ description: "Room ID supplied by Cohort, e.g. rooms:abc123" }),
|
|
14995
|
+
agent_names: Type.Array(Type.String({ description: "Cohort agent name to prompt" })),
|
|
14996
|
+
prompt: Type.String({ description: "Prompt to send to the target agents" })
|
|
14997
|
+
}),
|
|
14998
|
+
async execute(_toolCallId, params) {
|
|
14999
|
+
const rt = getToolRuntime();
|
|
15000
|
+
if (!rt.isReady) {
|
|
15001
|
+
return textResult("cohort_room_prompt_agents is not ready yet \u2014 the plugin is still starting up. Try again in a few seconds.");
|
|
15002
|
+
}
|
|
15003
|
+
const moderatorAgentName = rt.resolveAgentName(agentId);
|
|
15004
|
+
const result = await callPromptRoomAgentsFromPlugin(rt.apiKey, {
|
|
15005
|
+
roomId: params.room_id,
|
|
15006
|
+
moderatorAgentName,
|
|
15007
|
+
targetAgentNames: params.agent_names,
|
|
15008
|
+
prompt: params.prompt
|
|
15009
|
+
});
|
|
15010
|
+
const noun = result.notificationCount === 1 ? "agent" : "agents";
|
|
15011
|
+
return textResult(`Prompt sent to ${result.notificationCount} Room ${noun}.`, result);
|
|
15012
|
+
}
|
|
15013
|
+
};
|
|
15014
|
+
});
|
|
14874
15015
|
api.registerTool(() => {
|
|
14875
15016
|
return {
|
|
14876
15017
|
name: "cohort_context",
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"contracts": {
|
|
12
12
|
"tools": [
|
|
13
13
|
"cohort_comment",
|
|
14
|
+
"cohort_room_message",
|
|
15
|
+
"cohort_room_prompt_agent",
|
|
16
|
+
"cohort_room_prompt_agents",
|
|
14
17
|
"cohort_context",
|
|
15
18
|
"cohort_briefing_context",
|
|
16
19
|
"cohort_briefing",
|
|
@@ -74,5 +77,5 @@
|
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
},
|
|
77
|
-
"version": "0.31.
|
|
80
|
+
"version": "0.31.13"
|
|
78
81
|
}
|
package/dist/package.json
CHANGED
package/openclaw.plugin.json
CHANGED
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"contracts": {
|
|
10
10
|
"tools": [
|
|
11
11
|
"cohort_comment",
|
|
12
|
+
"cohort_room_message",
|
|
13
|
+
"cohort_room_prompt_agent",
|
|
14
|
+
"cohort_room_prompt_agents",
|
|
12
15
|
"cohort_context",
|
|
13
16
|
"cohort_briefing_context",
|
|
14
17
|
"cohort_briefing",
|
|
@@ -72,5 +75,5 @@
|
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
},
|
|
75
|
-
"version": "0.9.
|
|
78
|
+
"version": "0.9.3"
|
|
76
79
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cfio/cohort-sync",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.13",
|
|
4
4
|
"description": "OpenClaw plugin — syncs agent telemetry, sessions, and activity to the Cohort dashboard",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://docs.cohort.bot/gateway",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"esbuild": "^0.25.11",
|
|
40
|
-
"vitest": "^2.
|
|
40
|
+
"vitest": "^3.2.6"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"openclaw": ">=0.1.0"
|