@cfio/cohort-sync 0.31.6 → 0.31.8
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 +207 -24
- package/dist/openclaw.plugin.json +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11741,7 +11741,7 @@ function checkRateLimit() {
|
|
|
11741
11741
|
return true;
|
|
11742
11742
|
}
|
|
11743
11743
|
var MAX_CRON_MESSAGE_LENGTH = 1e3;
|
|
11744
|
-
async function executeCommand(cmd, gwClient, cfg, resolveAgentName, logger, cronTimestampTracker) {
|
|
11744
|
+
async function executeCommand(cmd, gwClient, cfg, resolveAgentName, logger, cronTimestampTracker, injection) {
|
|
11745
11745
|
logger.info(`cohort-sync: executing command type=${cmd.type} id=${cmd._id}`);
|
|
11746
11746
|
if (!checkRateLimit()) {
|
|
11747
11747
|
logger.warn(`cohort-sync: rate limit exceeded (>${RATE_LIMIT_MAX} commands/min), rejecting command ${cmd._id}`);
|
|
@@ -11764,6 +11764,23 @@ async function executeCommand(cmd, gwClient, cfg, resolveAgentName, logger, cron
|
|
|
11764
11764
|
process.kill(process.pid, "SIGUSR1");
|
|
11765
11765
|
return;
|
|
11766
11766
|
}
|
|
11767
|
+
if (cmd.type === "briefingGenerate") {
|
|
11768
|
+
const requestId = cmd.payload?.briefingRequestId;
|
|
11769
|
+
if (!requestId) {
|
|
11770
|
+
throw new Error("briefingRequestId is required for briefingGenerate");
|
|
11771
|
+
}
|
|
11772
|
+
if (!injection?.port || !injection.hooksToken) {
|
|
11773
|
+
throw new Error("Gateway hooks transport is not available for briefing generation");
|
|
11774
|
+
}
|
|
11775
|
+
const agentName = cmd.payload?.agentId ?? "main";
|
|
11776
|
+
const agentId = reverseResolveAgentName(agentName, cfg.agentNameMap ?? {});
|
|
11777
|
+
await injectBriefingGeneration(injection.port, injection.hooksToken, {
|
|
11778
|
+
requestId,
|
|
11779
|
+
agentId,
|
|
11780
|
+
agentName
|
|
11781
|
+
});
|
|
11782
|
+
return;
|
|
11783
|
+
}
|
|
11767
11784
|
if (cmd.type.startsWith("cron")) {
|
|
11768
11785
|
if (!gwClient || !gwClient.isAlive()) {
|
|
11769
11786
|
logger.warn(`cohort-sync: no gateway client, cannot execute ${cmd.type}`);
|
|
@@ -11971,6 +11988,7 @@ var acknowledgeCommandRef = makeFunctionReference("gatewayCommands:acknowledgeCo
|
|
|
11971
11988
|
var failCommandRef = makeFunctionReference("gatewayCommands:failCommand");
|
|
11972
11989
|
var getChannelsForPlugin = makeFunctionReference("cloudGatewayChannels:listForPlugin");
|
|
11973
11990
|
var addCommentFromPluginRef = makeFunctionReference("comments:addCommentFromPlugin");
|
|
11991
|
+
var transitionFromPluginRef = makeFunctionReference("tasks:transitionFromPlugin");
|
|
11974
11992
|
async function pushTelemetry(apiKey2, data) {
|
|
11975
11993
|
if (authCircuitOpen) return;
|
|
11976
11994
|
const c = getClient();
|
|
@@ -12073,6 +12091,30 @@ async function callAddCommentFromPlugin(apiKey2, args) {
|
|
|
12073
12091
|
throw err;
|
|
12074
12092
|
}
|
|
12075
12093
|
}
|
|
12094
|
+
async function callTransitionFromPlugin(apiKey2, args) {
|
|
12095
|
+
if (authCircuitOpen) {
|
|
12096
|
+
throw new Error(
|
|
12097
|
+
'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_..."'
|
|
12098
|
+
);
|
|
12099
|
+
}
|
|
12100
|
+
const c = getClient();
|
|
12101
|
+
if (!c) {
|
|
12102
|
+
throw new Error("Convex client not initialized \u2014 subscription may not be active");
|
|
12103
|
+
}
|
|
12104
|
+
try {
|
|
12105
|
+
return await c.mutation(transitionFromPluginRef, {
|
|
12106
|
+
apiKeyHash: hashApiKey(apiKey2),
|
|
12107
|
+
taskNumber: args.taskNumber,
|
|
12108
|
+
agentName: args.agentName,
|
|
12109
|
+
targetStatus: args.targetStatus
|
|
12110
|
+
});
|
|
12111
|
+
} catch (err) {
|
|
12112
|
+
if (isUnauthorizedError(err)) {
|
|
12113
|
+
tripAuthCircuit();
|
|
12114
|
+
}
|
|
12115
|
+
throw err;
|
|
12116
|
+
}
|
|
12117
|
+
}
|
|
12076
12118
|
var DEFAULT_BEHAVIORAL_PROMPT = `BEFORE RESPONDING:
|
|
12077
12119
|
- Does your planned response address the task's stated scope? If not, do not comment.
|
|
12078
12120
|
- Do not post acknowledgment-only responses ("got it", "sounds good", "confirmed"). If you have no new information to add, do not comment.
|
|
@@ -12184,6 +12226,46 @@ async function injectNotification(port, hooksToken, n, agentId = "main") {
|
|
|
12184
12226
|
throw new Error(`/hooks/agent returned ${response.status} ${response.statusText}`);
|
|
12185
12227
|
}
|
|
12186
12228
|
}
|
|
12229
|
+
function buildBriefingGenerationMessage(args) {
|
|
12230
|
+
return `Generate the Cohort Home briefing requested for ${args.agentName}.
|
|
12231
|
+
|
|
12232
|
+
Use your own voice and persona from SOUL.md, IDENTITY.md, and the rest of your agent instructions. First call cohort_briefing_context with request_id "${args.requestId}" to read the prepared workspace context. Then write the final briefing and submit it with cohort_briefing.
|
|
12233
|
+
|
|
12234
|
+
Final briefing requirements:
|
|
12235
|
+
- Write exactly two short paragraphs.
|
|
12236
|
+
- No bullet points or numbered lists.
|
|
12237
|
+
- Do not mention "this briefing".
|
|
12238
|
+
- Avoid colon-heavy phrasing.
|
|
12239
|
+
- Include one concrete high-leverage thing the reader should direct attention to next.
|
|
12240
|
+
- Keep it useful, personal, and alive without sounding theatrical.
|
|
12241
|
+
|
|
12242
|
+
TOOLS:
|
|
12243
|
+
- cohort_briefing_context(request_id) \u2014 fetch the prepared briefing context.
|
|
12244
|
+
- cohort_briefing(request_id, content) \u2014 submit the final Home briefing.`;
|
|
12245
|
+
}
|
|
12246
|
+
async function injectBriefingGeneration(port, hooksToken, args) {
|
|
12247
|
+
const response = await fetch(`http://localhost:${port}/hooks/agent`, {
|
|
12248
|
+
method: "POST",
|
|
12249
|
+
headers: {
|
|
12250
|
+
"Content-Type": "application/json",
|
|
12251
|
+
"Authorization": `Bearer ${hooksToken}`
|
|
12252
|
+
},
|
|
12253
|
+
body: JSON.stringify({
|
|
12254
|
+
message: buildBriefingGenerationMessage({
|
|
12255
|
+
requestId: args.requestId,
|
|
12256
|
+
agentName: args.agentName
|
|
12257
|
+
}),
|
|
12258
|
+
name: "Cohort",
|
|
12259
|
+
agentId: args.agentId,
|
|
12260
|
+
deliver: false,
|
|
12261
|
+
sessionKey: args.agentId === "main" ? `hook:cohort:briefing-${args.requestId}` : `agent:${args.agentId}:hook:cohort:briefing-${args.requestId}`
|
|
12262
|
+
}),
|
|
12263
|
+
signal: AbortSignal.timeout(1e4)
|
|
12264
|
+
});
|
|
12265
|
+
if (!response.ok) {
|
|
12266
|
+
throw new Error(`/hooks/agent returned ${response.status} ${response.statusText}`);
|
|
12267
|
+
}
|
|
12268
|
+
}
|
|
12187
12269
|
var deliveryFailures = /* @__PURE__ */ new Map();
|
|
12188
12270
|
var MAX_DELIVERY_ATTEMPTS = 3;
|
|
12189
12271
|
async function startNotificationSubscription(port, cfg, hooksToken, logger, gwClient, resolvedNameMap) {
|
|
@@ -12273,7 +12355,7 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
|
|
|
12273
12355
|
unsubscribers.push(unsubscribe);
|
|
12274
12356
|
}
|
|
12275
12357
|
}
|
|
12276
|
-
function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronTimestampTracker) {
|
|
12358
|
+
function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronTimestampTracker, injection) {
|
|
12277
12359
|
const c = getClient();
|
|
12278
12360
|
if (!c) {
|
|
12279
12361
|
logger.warn("cohort-sync: no ConvexClient \u2014 command subscription skipped");
|
|
@@ -12296,7 +12378,15 @@ function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronT
|
|
|
12296
12378
|
commandId: cmd._id,
|
|
12297
12379
|
apiKeyHash
|
|
12298
12380
|
});
|
|
12299
|
-
await executeCommand(
|
|
12381
|
+
await executeCommand(
|
|
12382
|
+
cmd,
|
|
12383
|
+
gwClient,
|
|
12384
|
+
cfg,
|
|
12385
|
+
resolveAgentName,
|
|
12386
|
+
logger,
|
|
12387
|
+
cronTimestampTracker,
|
|
12388
|
+
injection
|
|
12389
|
+
);
|
|
12300
12390
|
if (cmd.type === "restart") return;
|
|
12301
12391
|
} catch (err) {
|
|
12302
12392
|
if (isUnauthorizedError(err)) {
|
|
@@ -13640,7 +13730,7 @@ function dumpEvent(event) {
|
|
|
13640
13730
|
function positiveNumber(value) {
|
|
13641
13731
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
13642
13732
|
}
|
|
13643
|
-
var PLUGIN_VERSION = true ? "0.31.
|
|
13733
|
+
var PLUGIN_VERSION = true ? "0.31.8" : "unknown";
|
|
13644
13734
|
function resolveGatewayToken(api) {
|
|
13645
13735
|
const token2 = api.config?.gateway?.auth?.token;
|
|
13646
13736
|
return typeof token2 === "string" ? token2 : null;
|
|
@@ -13839,7 +13929,14 @@ async function handleGatewayStart(event, state) {
|
|
|
13839
13929
|
state.commandUnsubscriber();
|
|
13840
13930
|
state.commandUnsubscriber = null;
|
|
13841
13931
|
}
|
|
13842
|
-
const unsub = startCommandSubscription(
|
|
13932
|
+
const unsub = startCommandSubscription(
|
|
13933
|
+
cfg,
|
|
13934
|
+
logger,
|
|
13935
|
+
state.resolveAgentName,
|
|
13936
|
+
state.persistentGwClient,
|
|
13937
|
+
state.cronTimestampTracker,
|
|
13938
|
+
{ port: state.gatewayPort, hooksToken: state.gatewayToken }
|
|
13939
|
+
);
|
|
13843
13940
|
state.commandUnsubscriber = unsub;
|
|
13844
13941
|
} catch (err) {
|
|
13845
13942
|
logger.debug("cohort-sync: gateway client connect failed", { error: String(err) });
|
|
@@ -14169,7 +14266,14 @@ function registerHookHandlers(api, logger, getState) {
|
|
|
14169
14266
|
state.commandUnsubscriber();
|
|
14170
14267
|
state.commandUnsubscriber = null;
|
|
14171
14268
|
}
|
|
14172
|
-
const unsub = startCommandSubscription(
|
|
14269
|
+
const unsub = startCommandSubscription(
|
|
14270
|
+
cfg,
|
|
14271
|
+
log,
|
|
14272
|
+
state.resolveAgentName,
|
|
14273
|
+
state.persistentGwClient,
|
|
14274
|
+
state.cronTimestampTracker,
|
|
14275
|
+
{ port: state.gatewayPort, hooksToken: state.gatewayToken }
|
|
14276
|
+
);
|
|
14173
14277
|
state.commandUnsubscriber = unsub;
|
|
14174
14278
|
} catch (err) {
|
|
14175
14279
|
log.debug("cohort-sync: gateway client lazy init failed", { error: String(err) });
|
|
@@ -14485,7 +14589,14 @@ function initializeHookState(api, cfg) {
|
|
|
14485
14589
|
persistentGwClient = client2;
|
|
14486
14590
|
gwClientInitialized = true;
|
|
14487
14591
|
}
|
|
14488
|
-
const commandUnsub = startCommandSubscription(
|
|
14592
|
+
const commandUnsub = startCommandSubscription(
|
|
14593
|
+
cfg,
|
|
14594
|
+
logger,
|
|
14595
|
+
resolveAgentName,
|
|
14596
|
+
persistentGwClient,
|
|
14597
|
+
cronTimestampTracker,
|
|
14598
|
+
{ port: gatewayPort, hooksToken: gatewayToken }
|
|
14599
|
+
);
|
|
14489
14600
|
setToolRuntime({
|
|
14490
14601
|
apiKey: cfg.apiKey,
|
|
14491
14602
|
apiUrl: cfg.apiUrl,
|
|
@@ -14769,6 +14880,86 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14769
14880
|
}
|
|
14770
14881
|
};
|
|
14771
14882
|
});
|
|
14883
|
+
api.registerTool((toolCtx) => {
|
|
14884
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14885
|
+
return {
|
|
14886
|
+
name: "cohort_briefing_context",
|
|
14887
|
+
label: "cohort_briefing_context",
|
|
14888
|
+
description: "Fetch the prepared workspace context for a Cohort Home briefing request.",
|
|
14889
|
+
parameters: Type.Object({
|
|
14890
|
+
request_id: Type.String({ description: "Briefing request ID supplied by Cohort." })
|
|
14891
|
+
}),
|
|
14892
|
+
async execute(_toolCallId, params) {
|
|
14893
|
+
const rt = getToolRuntime();
|
|
14894
|
+
if (!rt.isReady) {
|
|
14895
|
+
return textResult("cohort_briefing_context is not ready yet \u2014 the plugin is still starting up.");
|
|
14896
|
+
}
|
|
14897
|
+
try {
|
|
14898
|
+
const response = await fetch(
|
|
14899
|
+
`${rt.apiUrl}/api/v1/briefings/${encodeURIComponent(params.request_id)}/context`,
|
|
14900
|
+
{
|
|
14901
|
+
method: "GET",
|
|
14902
|
+
headers: { "Authorization": `Bearer ${rt.apiKey}` },
|
|
14903
|
+
signal: AbortSignal.timeout(1e4)
|
|
14904
|
+
}
|
|
14905
|
+
);
|
|
14906
|
+
const body = await response.text();
|
|
14907
|
+
if (!response.ok) {
|
|
14908
|
+
return textResult(`Failed to fetch briefing context: ${response.status} ${body.slice(0, 300)}`);
|
|
14909
|
+
}
|
|
14910
|
+
const agentName = rt.resolveAgentName(agentId);
|
|
14911
|
+
return textResult(
|
|
14912
|
+
`Briefing context for ${agentName}:
|
|
14913
|
+
|
|
14914
|
+
${body}`,
|
|
14915
|
+
JSON.parse(body)
|
|
14916
|
+
);
|
|
14917
|
+
} catch (err) {
|
|
14918
|
+
return textResult(`Failed to fetch briefing context: ${err instanceof Error ? err.message : String(err)}`);
|
|
14919
|
+
}
|
|
14920
|
+
}
|
|
14921
|
+
};
|
|
14922
|
+
});
|
|
14923
|
+
api.registerTool((toolCtx) => {
|
|
14924
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14925
|
+
return {
|
|
14926
|
+
name: "cohort_briefing",
|
|
14927
|
+
label: "cohort_briefing",
|
|
14928
|
+
description: "Submit the final generated text for a Cohort Home briefing request.",
|
|
14929
|
+
parameters: Type.Object({
|
|
14930
|
+
request_id: Type.String({ description: "Briefing request ID supplied by Cohort." }),
|
|
14931
|
+
content: Type.String({ description: "Final briefing text. Use exactly two short paragraphs." })
|
|
14932
|
+
}),
|
|
14933
|
+
async execute(_toolCallId, params) {
|
|
14934
|
+
const rt = getToolRuntime();
|
|
14935
|
+
if (!rt.isReady) {
|
|
14936
|
+
return textResult("cohort_briefing is not ready yet \u2014 the plugin is still starting up.");
|
|
14937
|
+
}
|
|
14938
|
+
const agentName = rt.resolveAgentName(agentId);
|
|
14939
|
+
try {
|
|
14940
|
+
const response = await fetch(
|
|
14941
|
+
`${rt.apiUrl}/api/v1/briefings/${encodeURIComponent(params.request_id)}`,
|
|
14942
|
+
{
|
|
14943
|
+
method: "POST",
|
|
14944
|
+
headers: {
|
|
14945
|
+
"Authorization": `Bearer ${rt.apiKey}`,
|
|
14946
|
+
"Content-Type": "application/json"
|
|
14947
|
+
},
|
|
14948
|
+
body: JSON.stringify({ agentName, content: params.content }),
|
|
14949
|
+
signal: AbortSignal.timeout(1e4)
|
|
14950
|
+
}
|
|
14951
|
+
);
|
|
14952
|
+
const body = await response.text();
|
|
14953
|
+
if (!response.ok) {
|
|
14954
|
+
return textResult(`Failed to submit briefing: ${response.status} ${body.slice(0, 300)}`);
|
|
14955
|
+
}
|
|
14956
|
+
return textResult("Briefing submitted.", JSON.parse(body));
|
|
14957
|
+
} catch (err) {
|
|
14958
|
+
return textResult(`Failed to submit briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
14959
|
+
}
|
|
14960
|
+
}
|
|
14961
|
+
};
|
|
14962
|
+
});
|
|
14772
14963
|
api.registerTool(() => {
|
|
14773
14964
|
return {
|
|
14774
14965
|
name: "cohort_task",
|
|
@@ -14832,7 +15023,8 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14832
15023
|
}
|
|
14833
15024
|
};
|
|
14834
15025
|
});
|
|
14835
|
-
api.registerTool(() => {
|
|
15026
|
+
api.registerTool((toolCtx) => {
|
|
15027
|
+
const agentId = toolCtx.agentId ?? "main";
|
|
14836
15028
|
return {
|
|
14837
15029
|
name: "cohort_transition",
|
|
14838
15030
|
label: "cohort_transition",
|
|
@@ -14850,21 +15042,13 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14850
15042
|
if (!validStatuses.includes(params.status)) {
|
|
14851
15043
|
return textResult(`Invalid status "${params.status}". Valid statuses: ${validStatuses.join(", ")}`);
|
|
14852
15044
|
}
|
|
15045
|
+
const agentName = rt.resolveAgentName(agentId);
|
|
14853
15046
|
try {
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
"Content-Type": "application/json"
|
|
14859
|
-
},
|
|
14860
|
-
body: JSON.stringify({ to: params.status }),
|
|
14861
|
-
signal: AbortSignal.timeout(1e4)
|
|
15047
|
+
await callTransitionFromPlugin(rt.apiKey, {
|
|
15048
|
+
taskNumber: params.task_number,
|
|
15049
|
+
agentName,
|
|
15050
|
+
targetStatus: params.status
|
|
14862
15051
|
});
|
|
14863
|
-
if (!res.ok) {
|
|
14864
|
-
const body = await res.text();
|
|
14865
|
-
return textResult(`Failed to transition task #${params.task_number} to "${params.status}": ${res.status} ${body.slice(0, 200)}`);
|
|
14866
|
-
}
|
|
14867
|
-
const task = await res.json();
|
|
14868
15052
|
return textResult(`Task #${params.task_number} transitioned to "${params.status}".`);
|
|
14869
15053
|
} catch (err) {
|
|
14870
15054
|
return textResult(`Failed to transition task #${params.task_number}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -14872,8 +15056,7 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14872
15056
|
}
|
|
14873
15057
|
};
|
|
14874
15058
|
});
|
|
14875
|
-
api.registerTool((
|
|
14876
|
-
const agentId = toolCtx.agentId ?? "main";
|
|
15059
|
+
api.registerTool(() => {
|
|
14877
15060
|
return {
|
|
14878
15061
|
name: "cohort_assign",
|
|
14879
15062
|
label: "cohort_assign",
|
|
@@ -14905,7 +15088,7 @@ Do not attempt more comments until tomorrow.`);
|
|
|
14905
15088
|
const body = await res.text();
|
|
14906
15089
|
return textResult(`Failed to assign task #${params.task_number}: ${res.status} ${body.slice(0, 200)}`);
|
|
14907
15090
|
}
|
|
14908
|
-
|
|
15091
|
+
await res.json();
|
|
14909
15092
|
const msg = assignee ? `Task #${params.task_number} assigned to ${assignee}.` : `Task #${params.task_number} unassigned.`;
|
|
14910
15093
|
return textResult(msg);
|
|
14911
15094
|
} catch (err) {
|
package/dist/package.json
CHANGED
package/package.json
CHANGED