@cfio/cohort-sync 0.31.7 → 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 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}`);
@@ -12209,6 +12226,46 @@ async function injectNotification(port, hooksToken, n, agentId = "main") {
12209
12226
  throw new Error(`/hooks/agent returned ${response.status} ${response.statusText}`);
12210
12227
  }
12211
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
+ }
12212
12269
  var deliveryFailures = /* @__PURE__ */ new Map();
12213
12270
  var MAX_DELIVERY_ATTEMPTS = 3;
12214
12271
  async function startNotificationSubscription(port, cfg, hooksToken, logger, gwClient, resolvedNameMap) {
@@ -12298,7 +12355,7 @@ async function startNotificationSubscription(port, cfg, hooksToken, logger, gwCl
12298
12355
  unsubscribers.push(unsubscribe);
12299
12356
  }
12300
12357
  }
12301
- function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronTimestampTracker) {
12358
+ function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronTimestampTracker, injection) {
12302
12359
  const c = getClient();
12303
12360
  if (!c) {
12304
12361
  logger.warn("cohort-sync: no ConvexClient \u2014 command subscription skipped");
@@ -12321,7 +12378,15 @@ function startCommandSubscription(cfg, logger, resolveAgentName, gwClient, cronT
12321
12378
  commandId: cmd._id,
12322
12379
  apiKeyHash
12323
12380
  });
12324
- await executeCommand(cmd, gwClient, cfg, resolveAgentName, logger, cronTimestampTracker);
12381
+ await executeCommand(
12382
+ cmd,
12383
+ gwClient,
12384
+ cfg,
12385
+ resolveAgentName,
12386
+ logger,
12387
+ cronTimestampTracker,
12388
+ injection
12389
+ );
12325
12390
  if (cmd.type === "restart") return;
12326
12391
  } catch (err) {
12327
12392
  if (isUnauthorizedError(err)) {
@@ -13665,7 +13730,7 @@ function dumpEvent(event) {
13665
13730
  function positiveNumber(value) {
13666
13731
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
13667
13732
  }
13668
- var PLUGIN_VERSION = true ? "0.31.7" : "unknown";
13733
+ var PLUGIN_VERSION = true ? "0.31.8" : "unknown";
13669
13734
  function resolveGatewayToken(api) {
13670
13735
  const token2 = api.config?.gateway?.auth?.token;
13671
13736
  return typeof token2 === "string" ? token2 : null;
@@ -13864,7 +13929,14 @@ async function handleGatewayStart(event, state) {
13864
13929
  state.commandUnsubscriber();
13865
13930
  state.commandUnsubscriber = null;
13866
13931
  }
13867
- const unsub = startCommandSubscription(cfg, logger, state.resolveAgentName, state.persistentGwClient, state.cronTimestampTracker);
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
+ );
13868
13940
  state.commandUnsubscriber = unsub;
13869
13941
  } catch (err) {
13870
13942
  logger.debug("cohort-sync: gateway client connect failed", { error: String(err) });
@@ -14194,7 +14266,14 @@ function registerHookHandlers(api, logger, getState) {
14194
14266
  state.commandUnsubscriber();
14195
14267
  state.commandUnsubscriber = null;
14196
14268
  }
14197
- const unsub = startCommandSubscription(cfg, log, state.resolveAgentName, state.persistentGwClient, state.cronTimestampTracker);
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
+ );
14198
14277
  state.commandUnsubscriber = unsub;
14199
14278
  } catch (err) {
14200
14279
  log.debug("cohort-sync: gateway client lazy init failed", { error: String(err) });
@@ -14510,7 +14589,14 @@ function initializeHookState(api, cfg) {
14510
14589
  persistentGwClient = client2;
14511
14590
  gwClientInitialized = true;
14512
14591
  }
14513
- const commandUnsub = startCommandSubscription(cfg, logger, resolveAgentName, persistentGwClient, cronTimestampTracker);
14592
+ const commandUnsub = startCommandSubscription(
14593
+ cfg,
14594
+ logger,
14595
+ resolveAgentName,
14596
+ persistentGwClient,
14597
+ cronTimestampTracker,
14598
+ { port: gatewayPort, hooksToken: gatewayToken }
14599
+ );
14514
14600
  setToolRuntime({
14515
14601
  apiKey: cfg.apiKey,
14516
14602
  apiUrl: cfg.apiUrl,
@@ -14794,6 +14880,86 @@ Do not attempt more comments until tomorrow.`);
14794
14880
  }
14795
14881
  };
14796
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
+ });
14797
14963
  api.registerTool(() => {
14798
14964
  return {
14799
14965
  name: "cohort_task",
@@ -72,5 +72,5 @@
72
72
  }
73
73
  }
74
74
  },
75
- "version": "0.31.7"
75
+ "version": "0.31.8"
76
76
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.31.7",
3
+ "version": "0.31.8",
4
4
  "description": "OpenClaw plugin — syncs agent telemetry, sessions, and activity to the Cohort dashboard",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.31.7",
3
+ "version": "0.31.8",
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",