@cfio/cohort-sync 0.34.0 → 0.34.2
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 +189 -6
- package/dist/openclaw.plugin.json +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12183,7 +12183,9 @@ async function callPublishWireFromPlugin(apiKey2, args) {
|
|
|
12183
12183
|
...args.filename !== void 0 ? { filename: args.filename } : {},
|
|
12184
12184
|
...args.altText !== void 0 ? { altText: args.altText } : {},
|
|
12185
12185
|
...args.roomId !== void 0 ? { roomId: args.roomId } : {},
|
|
12186
|
-
...args.taskId !== void 0 ? { taskId: args.taskId } : {}
|
|
12186
|
+
...args.taskId !== void 0 ? { taskId: args.taskId } : {},
|
|
12187
|
+
...args.inResponseToSteerId !== void 0 ? { inResponseToSteerId: args.inResponseToSteerId } : {},
|
|
12188
|
+
...args.deliveryNote !== void 0 ? { deliveryNote: args.deliveryNote } : {}
|
|
12187
12189
|
});
|
|
12188
12190
|
} catch (err) {
|
|
12189
12191
|
if (isUnauthorizedError(err)) {
|
|
@@ -14117,7 +14119,7 @@ function dumpEvent(event) {
|
|
|
14117
14119
|
function positiveNumber(value) {
|
|
14118
14120
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
14119
14121
|
}
|
|
14120
|
-
var PLUGIN_VERSION = true ? "0.34.
|
|
14122
|
+
var PLUGIN_VERSION = true ? "0.34.2" : "unknown";
|
|
14121
14123
|
function resolveGatewayToken(api) {
|
|
14122
14124
|
const token2 = api.config?.gateway?.auth?.token;
|
|
14123
14125
|
return typeof token2 === "string" ? token2 : null;
|
|
@@ -15144,6 +15146,7 @@ var WIRE_FILENAME_MAX = 200;
|
|
|
15144
15146
|
var WIRE_MIME_TYPE_MAX = 100;
|
|
15145
15147
|
var WIRE_ALT_TEXT_MAX = 1e3;
|
|
15146
15148
|
var WIRE_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
15149
|
+
var WIRE_DELIVERY_NOTE_MAX = 1e3;
|
|
15147
15150
|
function wireInvalid(message) {
|
|
15148
15151
|
return textResult(`Cannot publish to Wire: ${message}.`);
|
|
15149
15152
|
}
|
|
@@ -15209,9 +15212,87 @@ function getStorageIdFromUploadResponse(body) {
|
|
|
15209
15212
|
function formatMetric(metric) {
|
|
15210
15213
|
return `${metric.current}/${metric.target} ${metric.unit}`;
|
|
15211
15214
|
}
|
|
15215
|
+
function isRecord2(value) {
|
|
15216
|
+
return typeof value === "object" && value !== null;
|
|
15217
|
+
}
|
|
15212
15218
|
function redactSecrets(text) {
|
|
15213
15219
|
return text.replace(/ch_(?:live|test)_[A-Za-z0-9_-]+/g, "[redacted]");
|
|
15214
15220
|
}
|
|
15221
|
+
function isTaskRelationSummary(value) {
|
|
15222
|
+
if (!isRecord2(value) || !isRecord2(value.task)) return false;
|
|
15223
|
+
return typeof value.id === "string" && (value.type === "blocks" || value.type === "related" || value.type === "duplicate_of") && (value.direction === "incoming" || value.direction === "outgoing") && (value.task.taskNumber === void 0 || typeof value.task.taskNumber === "number") && (value.task.title === void 0 || typeof value.task.title === "string") && typeof value.task.status === "string" && (typeof value.task.assignedTo === "string" || value.task.assignedTo === null);
|
|
15224
|
+
}
|
|
15225
|
+
function relationTaskLabel(relation) {
|
|
15226
|
+
const id = relation.task.taskNumber !== void 0 ? `#${relation.task.taskNumber}` : relation.task.title ?? "untitled task";
|
|
15227
|
+
return `${id} (${relation.task.status}, ${relation.task.assignedTo ?? "unassigned"})`;
|
|
15228
|
+
}
|
|
15229
|
+
function formatTaskRelationsSummary(relations) {
|
|
15230
|
+
if (!Array.isArray(relations)) return [];
|
|
15231
|
+
const rows = relations.filter(isTaskRelationSummary);
|
|
15232
|
+
if (rows.length === 0) return [];
|
|
15233
|
+
const groups = [
|
|
15234
|
+
{ label: "Blocked by", rows: rows.filter((r) => r.type === "blocks" && r.direction === "incoming") },
|
|
15235
|
+
{ label: "Blocks", rows: rows.filter((r) => r.type === "blocks" && r.direction === "outgoing") },
|
|
15236
|
+
{ label: "Related", rows: rows.filter((r) => r.type === "related") },
|
|
15237
|
+
{ label: "Duplicate of", rows: rows.filter((r) => r.type === "duplicate_of" && r.direction === "outgoing") },
|
|
15238
|
+
{ label: "Duplicated by", rows: rows.filter((r) => r.type === "duplicate_of" && r.direction === "incoming") }
|
|
15239
|
+
];
|
|
15240
|
+
return groups.filter((group) => group.rows.length > 0).map((group) => `${group.label}: ${group.rows.map(relationTaskLabel).join(", ")}`);
|
|
15241
|
+
}
|
|
15242
|
+
function blockerLine(blocker) {
|
|
15243
|
+
const id = blocker.taskNumber !== void 0 ? `#${blocker.taskNumber}` : "Unnumbered task";
|
|
15244
|
+
return `${id} ${blocker.title} (${blocker.status}, ${blocker.assignedTo ?? "unassigned"})`;
|
|
15245
|
+
}
|
|
15246
|
+
function getTaskBlockedErrorData(error) {
|
|
15247
|
+
if (!isRecord2(error) || !isRecord2(error.data)) return null;
|
|
15248
|
+
const data = error.data;
|
|
15249
|
+
if (data.code !== "CONFLICT" || data.subcode !== "TASK_BLOCKED" || typeof data.message !== "string") {
|
|
15250
|
+
return null;
|
|
15251
|
+
}
|
|
15252
|
+
const blockers = Array.isArray(data.blockers) ? data.blockers.flatMap((blocker) => {
|
|
15253
|
+
if (!isRecord2(blocker) || typeof blocker.title !== "string" || typeof blocker.status !== "string") {
|
|
15254
|
+
return [];
|
|
15255
|
+
}
|
|
15256
|
+
const assignedTo = typeof blocker.assignedTo === "string" ? blocker.assignedTo : null;
|
|
15257
|
+
return [{
|
|
15258
|
+
...typeof blocker.taskNumber === "number" ? { taskNumber: blocker.taskNumber } : {},
|
|
15259
|
+
title: blocker.title,
|
|
15260
|
+
status: blocker.status,
|
|
15261
|
+
assignedTo
|
|
15262
|
+
}];
|
|
15263
|
+
}) : void 0;
|
|
15264
|
+
return {
|
|
15265
|
+
code: "CONFLICT",
|
|
15266
|
+
subcode: "TASK_BLOCKED",
|
|
15267
|
+
message: data.message,
|
|
15268
|
+
...blockers ? { blockers } : {}
|
|
15269
|
+
};
|
|
15270
|
+
}
|
|
15271
|
+
function formatTaskBlockedError(error) {
|
|
15272
|
+
const data = getTaskBlockedErrorData(error);
|
|
15273
|
+
if (!data) return null;
|
|
15274
|
+
const lines = [data.message];
|
|
15275
|
+
if (data.blockers && data.blockers.length > 0) {
|
|
15276
|
+
lines.push("", "Open blockers:");
|
|
15277
|
+
for (const blocker of data.blockers) {
|
|
15278
|
+
lines.push(`- ${blockerLine(blocker)}`);
|
|
15279
|
+
}
|
|
15280
|
+
}
|
|
15281
|
+
return lines.join("\n");
|
|
15282
|
+
}
|
|
15283
|
+
function relationMatchesVerb(relation, relationVerb, otherTaskNumber) {
|
|
15284
|
+
if (relation.task.taskNumber !== otherTaskNumber) return false;
|
|
15285
|
+
switch (relationVerb) {
|
|
15286
|
+
case "blocked_by":
|
|
15287
|
+
return relation.type === "blocks" && relation.direction === "incoming";
|
|
15288
|
+
case "blocks":
|
|
15289
|
+
return relation.type === "blocks" && relation.direction === "outgoing";
|
|
15290
|
+
case "related":
|
|
15291
|
+
return relation.type === "related";
|
|
15292
|
+
case "duplicate_of":
|
|
15293
|
+
return relation.type === "duplicate_of" && relation.direction === "outgoing";
|
|
15294
|
+
}
|
|
15295
|
+
}
|
|
15215
15296
|
async function safeHttpError(response) {
|
|
15216
15297
|
try {
|
|
15217
15298
|
const body = await response.text();
|
|
@@ -15486,7 +15567,9 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15486
15567
|
filename: Type.Optional(Type.String({ description: `Original image filename, max ${WIRE_FILENAME_MAX} characters. Used with kind=image.` })),
|
|
15487
15568
|
alt_text: Type.Optional(Type.String({ description: `Accessible image description, max ${WIRE_ALT_TEXT_MAX} characters. Used with kind=image.` })),
|
|
15488
15569
|
room_id: Type.Optional(Type.String({ description: "Optional Cohort Room ID to link this Wire item to." })),
|
|
15489
|
-
task_id: Type.Optional(Type.String({ description: "Optional Cohort task ID to link this Wire item to." }))
|
|
15570
|
+
task_id: Type.Optional(Type.String({ description: "Optional Cohort task ID to link this Wire item to." })),
|
|
15571
|
+
in_response_to_steer_id: Type.Optional(Type.String({ description: "Wire request ID when delivering a requested revision or follow-up." })),
|
|
15572
|
+
delivery_note: Type.Optional(Type.String({ description: `Short note for the requester, max ${WIRE_DELIVERY_NOTE_MAX} characters.` }))
|
|
15490
15573
|
}),
|
|
15491
15574
|
async execute(_toolCallId, params) {
|
|
15492
15575
|
const rt = getToolRuntime();
|
|
@@ -15501,6 +15584,10 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15501
15584
|
if (!roomId.ok) return wireInvalid(roomId.message);
|
|
15502
15585
|
const taskId = optionalWireString(params.task_id, "task_id", WIRE_TITLE_MAX);
|
|
15503
15586
|
if (!taskId.ok) return wireInvalid(taskId.message);
|
|
15587
|
+
const inResponseToSteerId = optionalWireString(params.in_response_to_steer_id, "in_response_to_steer_id", WIRE_TITLE_MAX);
|
|
15588
|
+
if (!inResponseToSteerId.ok) return wireInvalid(inResponseToSteerId.message);
|
|
15589
|
+
const deliveryNote = optionalWireString(params.delivery_note, "delivery_note", WIRE_DELIVERY_NOTE_MAX);
|
|
15590
|
+
if (!deliveryNote.ok) return wireInvalid(deliveryNote.message);
|
|
15504
15591
|
const agentName = rt.resolveAgentName(agentId);
|
|
15505
15592
|
if (params.kind === "report") {
|
|
15506
15593
|
const body = optionalWireString(params.body, "body", WIRE_BODY_MAX);
|
|
@@ -15513,7 +15600,9 @@ Do not attempt more comments until tomorrow.`);
|
|
|
15513
15600
|
brief: brief.value,
|
|
15514
15601
|
...body.value !== void 0 ? { body: body.value } : {},
|
|
15515
15602
|
...roomId.value !== void 0 ? { roomId: roomId.value } : {},
|
|
15516
|
-
...taskId.value !== void 0 ? { taskId: taskId.value } : {}
|
|
15603
|
+
...taskId.value !== void 0 ? { taskId: taskId.value } : {},
|
|
15604
|
+
...inResponseToSteerId.value !== void 0 ? { inResponseToSteerId: inResponseToSteerId.value } : {},
|
|
15605
|
+
...deliveryNote.value !== void 0 ? { deliveryNote: deliveryNote.value } : {}
|
|
15517
15606
|
});
|
|
15518
15607
|
return textResult(`Published report to Wire.
|
|
15519
15608
|
Wire item: ${result.wireItemId}`, result);
|
|
@@ -15562,7 +15651,9 @@ Wire item: ${result.wireItemId}`, result);
|
|
|
15562
15651
|
filename: filename.value,
|
|
15563
15652
|
altText: altText.value,
|
|
15564
15653
|
...roomId.value !== void 0 ? { roomId: roomId.value } : {},
|
|
15565
|
-
...taskId.value !== void 0 ? { taskId: taskId.value } : {}
|
|
15654
|
+
...taskId.value !== void 0 ? { taskId: taskId.value } : {},
|
|
15655
|
+
...inResponseToSteerId.value !== void 0 ? { inResponseToSteerId: inResponseToSteerId.value } : {},
|
|
15656
|
+
...deliveryNote.value !== void 0 ? { deliveryNote: deliveryNote.value } : {}
|
|
15566
15657
|
});
|
|
15567
15658
|
return textResult(`Published image to Wire.
|
|
15568
15659
|
Wire item: ${result.wireItemId}`, result);
|
|
@@ -15829,10 +15920,17 @@ ${body}`,
|
|
|
15829
15920
|
`**Assigned to:** ${task.assignedTo ?? "unassigned"}`,
|
|
15830
15921
|
`**Created:** ${task.createdAt}`
|
|
15831
15922
|
];
|
|
15923
|
+
if (task.blocked === true) {
|
|
15924
|
+
lines.push("**Blocked:** yes");
|
|
15925
|
+
}
|
|
15832
15926
|
const contextBlock = renderTaskContext(task.context);
|
|
15833
15927
|
if (contextBlock) {
|
|
15834
15928
|
lines.push("", contextBlock);
|
|
15835
15929
|
}
|
|
15930
|
+
const relationsSummary = formatTaskRelationsSummary(task.relations);
|
|
15931
|
+
if (relationsSummary.length > 0) {
|
|
15932
|
+
lines.push("", "## Relations", ...relationsSummary);
|
|
15933
|
+
}
|
|
15836
15934
|
lines.push("", "## Description", task.description || "(no description)");
|
|
15837
15935
|
if (params.include_comments !== false) {
|
|
15838
15936
|
const limit = params.comment_limit ?? 10;
|
|
@@ -15948,7 +16046,92 @@ ${renderGoal(goal)}`, goal);
|
|
|
15948
16046
|
});
|
|
15949
16047
|
return textResult(`Task #${params.task_number} transitioned to "${params.status}".`);
|
|
15950
16048
|
} catch (err) {
|
|
15951
|
-
|
|
16049
|
+
const blockedMessage = formatTaskBlockedError(err);
|
|
16050
|
+
if (blockedMessage) {
|
|
16051
|
+
return textResult(blockedMessage, getTaskBlockedErrorData(err));
|
|
16052
|
+
}
|
|
16053
|
+
const appMessage = getConvexAppErrorMessage(err);
|
|
16054
|
+
return textResult(`Failed to transition task #${params.task_number}: ${appMessage ?? (err instanceof Error ? err.message : String(err))}`);
|
|
16055
|
+
}
|
|
16056
|
+
}
|
|
16057
|
+
};
|
|
16058
|
+
});
|
|
16059
|
+
api.registerTool(() => {
|
|
16060
|
+
return {
|
|
16061
|
+
name: "cohort_relate",
|
|
16062
|
+
label: "cohort_relate",
|
|
16063
|
+
description: "Create or remove Cohort task relations by task number. This is THE way to decompose work into ordered blockers: create blocker tasks, then relate them with blocked_by or blocks so Cohort can sequence handoffs.",
|
|
16064
|
+
parameters: Type.Object({
|
|
16065
|
+
task_number: Type.Number({ description: "Primary task number (e.g. 214)." }),
|
|
16066
|
+
relation: Type.Union([
|
|
16067
|
+
Type.Literal("blocked_by"),
|
|
16068
|
+
Type.Literal("blocks"),
|
|
16069
|
+
Type.Literal("related"),
|
|
16070
|
+
Type.Literal("duplicate_of")
|
|
16071
|
+
], { description: "Relation from task_number to other_task_number." }),
|
|
16072
|
+
other_task_number: Type.Number({ description: "Other task number to relate to the primary task." }),
|
|
16073
|
+
remove: Type.Optional(Type.Boolean({ description: "Set true to remove the matching relation instead of creating it." }))
|
|
16074
|
+
}),
|
|
16075
|
+
async execute(_toolCallId, params) {
|
|
16076
|
+
const rt = getToolRuntime();
|
|
16077
|
+
if (!rt.isReady) {
|
|
16078
|
+
return textResult("cohort_relate is not ready yet \u2014 the plugin is still starting up.");
|
|
16079
|
+
}
|
|
16080
|
+
if (params.task_number === params.other_task_number) {
|
|
16081
|
+
return textResult("Cannot relate a task to itself.");
|
|
16082
|
+
}
|
|
16083
|
+
try {
|
|
16084
|
+
if (!params.remove) {
|
|
16085
|
+
const response = await fetch(`${rt.apiUrl}/api/v1/tasks/${params.task_number}/relations`, {
|
|
16086
|
+
method: "POST",
|
|
16087
|
+
headers: {
|
|
16088
|
+
"Authorization": `Bearer ${rt.apiKey}`,
|
|
16089
|
+
"Content-Type": "application/json"
|
|
16090
|
+
},
|
|
16091
|
+
body: JSON.stringify({
|
|
16092
|
+
type: params.relation,
|
|
16093
|
+
taskNumber: params.other_task_number
|
|
16094
|
+
}),
|
|
16095
|
+
signal: AbortSignal.timeout(1e4)
|
|
16096
|
+
});
|
|
16097
|
+
if (!response.ok) {
|
|
16098
|
+
const message = await safeHttpError(response);
|
|
16099
|
+
return textResult(`Failed to relate task #${params.task_number}: ${response.status}${message}`);
|
|
16100
|
+
}
|
|
16101
|
+
const relation2 = await response.json();
|
|
16102
|
+
return textResult(`Related task #${params.task_number} ${params.relation} #${params.other_task_number}.`, relation2);
|
|
16103
|
+
}
|
|
16104
|
+
const taskResponse = await fetch(`${rt.apiUrl}/api/v1/tasks/${params.task_number}`, {
|
|
16105
|
+
headers: { "Authorization": `Bearer ${rt.apiKey}` },
|
|
16106
|
+
signal: AbortSignal.timeout(1e4)
|
|
16107
|
+
});
|
|
16108
|
+
if (!taskResponse.ok) {
|
|
16109
|
+
const message = await safeHttpError(taskResponse);
|
|
16110
|
+
return textResult(`Failed to inspect task #${params.task_number}: ${taskResponse.status}${message}`);
|
|
16111
|
+
}
|
|
16112
|
+
const task = await taskResponse.json();
|
|
16113
|
+
const relations = Array.isArray(task.relations) ? task.relations.filter(isTaskRelationSummary) : [];
|
|
16114
|
+
const relation = relations.find(
|
|
16115
|
+
(candidate) => relationMatchesVerb(candidate, params.relation, params.other_task_number)
|
|
16116
|
+
);
|
|
16117
|
+
if (!relation) {
|
|
16118
|
+
return textResult(`No ${params.relation} relation found between task #${params.task_number} and #${params.other_task_number}.`);
|
|
16119
|
+
}
|
|
16120
|
+
const deleteResponse = await fetch(
|
|
16121
|
+
`${rt.apiUrl}/api/v1/tasks/${params.task_number}/relations/${encodeURIComponent(relation.id)}`,
|
|
16122
|
+
{
|
|
16123
|
+
method: "DELETE",
|
|
16124
|
+
headers: { "Authorization": `Bearer ${rt.apiKey}` },
|
|
16125
|
+
signal: AbortSignal.timeout(1e4)
|
|
16126
|
+
}
|
|
16127
|
+
);
|
|
16128
|
+
if (!deleteResponse.ok) {
|
|
16129
|
+
const message = await safeHttpError(deleteResponse);
|
|
16130
|
+
return textResult(`Failed to remove relation from task #${params.task_number}: ${deleteResponse.status}${message}`);
|
|
16131
|
+
}
|
|
16132
|
+
return textResult(`Removed ${params.relation} relation between task #${params.task_number} and #${params.other_task_number}.`);
|
|
16133
|
+
} catch (err) {
|
|
16134
|
+
return textResult(`Failed to relate task #${params.task_number}: ${err instanceof Error ? redactSecrets(err.message) : "Unknown error"}`);
|
|
15952
16135
|
}
|
|
15953
16136
|
}
|
|
15954
16137
|
};
|
package/dist/package.json
CHANGED
package/package.json
CHANGED