@defend-tech/opencode-optima 0.1.37 → 0.1.38
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 +98 -6
- package/dist/sanitize_cli.js +98 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9600,6 +9600,96 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
|
|
|
9600
9600
|
if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, fetchImpl });
|
|
9601
9601
|
throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
|
|
9602
9602
|
}
|
|
9603
|
+
function normalizeOpenCodeSessionMessages(result) {
|
|
9604
|
+
const data = result?.data ?? result;
|
|
9605
|
+
if (Array.isArray(data)) return [...data];
|
|
9606
|
+
if (Array.isArray(data?.messages)) return [...data.messages];
|
|
9607
|
+
if (Array.isArray(data?.items)) return [...data.items];
|
|
9608
|
+
return [];
|
|
9609
|
+
}
|
|
9610
|
+
async function readOpenCodeSessionMessages(client, { sessionId, limit = 20 } = {}) {
|
|
9611
|
+
if (typeof client?.session?.messages !== "function") return null;
|
|
9612
|
+
const attempts = [
|
|
9613
|
+
{ path: { id: sessionId }, query: { limit } },
|
|
9614
|
+
{ path: { sessionID: sessionId }, query: { limit } },
|
|
9615
|
+
{ id: sessionId, limit },
|
|
9616
|
+
{ sessionID: sessionId, limit }
|
|
9617
|
+
];
|
|
9618
|
+
let firstError = null;
|
|
9619
|
+
for (const attempt of attempts) {
|
|
9620
|
+
try {
|
|
9621
|
+
return normalizeOpenCodeSessionMessages(await client.session.messages(attempt));
|
|
9622
|
+
} catch (error) {
|
|
9623
|
+
firstError ??= error;
|
|
9624
|
+
}
|
|
9625
|
+
}
|
|
9626
|
+
throw firstError;
|
|
9627
|
+
}
|
|
9628
|
+
function openCodeMessageText(message) {
|
|
9629
|
+
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
9630
|
+
const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
|
|
9631
|
+
for (const part of partList) parts.push(part?.text, part?.content);
|
|
9632
|
+
return parts.filter((value) => typeof value === "string").join("\n");
|
|
9633
|
+
}
|
|
9634
|
+
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 3, delayMs = 25 } = {}) {
|
|
9635
|
+
let lastError = "message_verification_unavailable";
|
|
9636
|
+
for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
|
|
9637
|
+
try {
|
|
9638
|
+
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
|
|
9639
|
+
if (!afterMessages) return { ok: true, method: "verification_unavailable", skipped: true };
|
|
9640
|
+
const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
|
|
9641
|
+
if (beforeCount !== null && afterMessages.length > beforeCount) return { ok: true, method: "message_count", beforeCount, afterCount: afterMessages.length };
|
|
9642
|
+
const textNeedles = [expectedText, ...markers].map((value) => String(value || "").trim()).filter(Boolean);
|
|
9643
|
+
const haystack = afterMessages.slice(-20).map(openCodeMessageText).join("\n");
|
|
9644
|
+
const matched = textNeedles.find((needle) => haystack.includes(needle));
|
|
9645
|
+
if (matched) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length };
|
|
9646
|
+
lastError = "message_not_visible";
|
|
9647
|
+
} catch (error) {
|
|
9648
|
+
lastError = error.message || "message_verification_failed";
|
|
9649
|
+
}
|
|
9650
|
+
if (attempt < attempts - 1 && delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
9651
|
+
}
|
|
9652
|
+
return { ok: false, reason: lastError };
|
|
9653
|
+
}
|
|
9654
|
+
function buildClickUpMessageDeliveryBlockerComment({ taskId, sessionId, reason, action } = {}) {
|
|
9655
|
+
return [
|
|
9656
|
+
`Optima blocker: could not deliver ClickUp task ${taskId} to OpenCode session ${sessionId}.`,
|
|
9657
|
+
`Delivery verification failed after send${action ? ` (${action})` : ""}: ${reason || "message_delivery_failed"}.`,
|
|
9658
|
+
"The webhook did not mark this event as successfully routed; please inspect/replay the event or route the task manually.",
|
|
9659
|
+
clickUpNoAbandonmentRuleText()
|
|
9660
|
+
].join("\n");
|
|
9661
|
+
}
|
|
9662
|
+
async function postClickUpMessageDeliveryBlocker({ clickupClient, worktree, taskId, sessionId, reason, action } = {}) {
|
|
9663
|
+
const comment = buildClickUpMessageDeliveryBlockerComment({ taskId, sessionId, reason, action });
|
|
9664
|
+
if (typeof clickupClient?.postTaskComment !== "function") {
|
|
9665
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_blocker_comment_unavailable", taskId, sessionId, reason, action });
|
|
9666
|
+
return { ok: false, skipped: true, reason: "post_task_comment_unavailable", comment };
|
|
9667
|
+
}
|
|
9668
|
+
try {
|
|
9669
|
+
await clickupClient.postTaskComment({ taskId, comment });
|
|
9670
|
+
return { ok: true, comment };
|
|
9671
|
+
} catch (error) {
|
|
9672
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_blocker_comment_failed", taskId, sessionId, reason, action, message: error.message });
|
|
9673
|
+
return { ok: false, error: error.message, comment };
|
|
9674
|
+
}
|
|
9675
|
+
}
|
|
9676
|
+
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery } = {}) {
|
|
9677
|
+
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => null);
|
|
9678
|
+
await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl });
|
|
9679
|
+
let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages, expectedText: text, markers: eventMarkers });
|
|
9680
|
+
if (verification?.ok) return { ok: true, verification, fallback: false };
|
|
9681
|
+
const canFallbackDirect = Boolean(opencodeBaseUrl);
|
|
9682
|
+
if (canFallbackDirect) {
|
|
9683
|
+
const retryBeforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => beforeMessages);
|
|
9684
|
+
await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: true });
|
|
9685
|
+
verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages: retryBeforeMessages, expectedText: text, markers: eventMarkers });
|
|
9686
|
+
if (verification?.ok) return { ok: true, verification, fallback: true };
|
|
9687
|
+
}
|
|
9688
|
+
const reason = verification?.reason || "message_delivery_failed";
|
|
9689
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: canFallbackDirect });
|
|
9690
|
+
const blocker = await postClickUpMessageDeliveryBlocker({ clickupClient, worktree, taskId, sessionId, reason, action: canFallbackDirect ? "fallback_failed" : "verification_failed" });
|
|
9691
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect, blockerComment: blocker };
|
|
9692
|
+
}
|
|
9603
9693
|
function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", worktree = "", deliveryEvidencePath = "" }) {
|
|
9604
9694
|
const comment = clickUpCommentFromPayload(payload);
|
|
9605
9695
|
const commentText = clickUpCommentText(comment).trim();
|
|
@@ -9831,7 +9921,7 @@ async function withClickUpTaskRouteLock(taskId, operation) {
|
|
|
9831
9921
|
if (activeClickUpTaskRoutes.get(key) === current) activeClickUpTaskRoutes.delete(key);
|
|
9832
9922
|
}
|
|
9833
9923
|
}
|
|
9834
|
-
async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktree, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
|
|
9924
|
+
async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktree, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
|
|
9835
9925
|
const eventType = clickUpEventType(payload);
|
|
9836
9926
|
const eventKey = clickUpWebhookEventKey(payload);
|
|
9837
9927
|
const remembered = rememberClickUpWebhookEvent(state, eventKey);
|
|
@@ -9921,18 +10011,20 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
9921
10011
|
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_metadata_failed", taskId, sessionId: pendingSessionId, message: error.message });
|
|
9922
10012
|
throw error;
|
|
9923
10013
|
}
|
|
9924
|
-
await
|
|
10014
|
+
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId: pendingSessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
10015
|
+
if (!delivery.ok) return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
9925
10016
|
const nextMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(pendingMetadata, config.routing.metadataKey, pendingSessionId), config.routing.metadataKey);
|
|
9926
10017
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: nextMetadata });
|
|
9927
10018
|
const { [taskId]: _completedPending, ...remainingPending } = stateToPersist.pendingSessions || {};
|
|
9928
10019
|
stateToPersist = { ...stateToPersist, pendingSessions: remainingPending };
|
|
9929
|
-
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
10020
|
+
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryFallback: delivery.fallback });
|
|
9930
10021
|
}
|
|
9931
10022
|
const sessionId = String(existingSessionId);
|
|
9932
10023
|
if (await sessionExists(openCodeClient, sessionId)) {
|
|
9933
10024
|
if (typeof clickupClient?.updateTaskMetadata === "function") await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: metadataWithRouting });
|
|
9934
|
-
await
|
|
9935
|
-
return finish({
|
|
10025
|
+
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
10026
|
+
if (!delivery.ok) return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
10027
|
+
return finish({ ok: true, action: "sent_to_existing_session", taskId, sessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryFallback: delivery.fallback });
|
|
9936
10028
|
}
|
|
9937
10029
|
const at = now().toISOString();
|
|
9938
10030
|
const incidentComment = `Optima webhook could not route this ClickUp event because OpenCode session ${sessionId} is missing on host ${host} at ${at}. No replacement session was created automatically.`;
|
|
@@ -11827,7 +11919,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
11827
11919
|
}
|
|
11828
11920
|
};
|
|
11829
11921
|
}
|
|
11830
|
-
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, readClickUpCommentLedger, readClickUpWebhookState, reconcileClickUpStartup, recordClickUpCommentVersionProcessed, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
11922
|
+
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, readClickUpCommentLedger, readClickUpWebhookState, reconcileClickUpStartup, recordClickUpCommentVersionProcessed, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
11831
11923
|
export {
|
|
11832
11924
|
OptimaPlugin as default
|
|
11833
11925
|
};
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -9607,6 +9607,96 @@ async function sendOpenCodeSessionEvent(client, { sessionId, agent, text, direct
|
|
|
9607
9607
|
if (directBaseUrl) return sendOpenCodeSessionEventDirect({ baseUrl: directBaseUrl, sessionId, text, fetchImpl });
|
|
9608
9608
|
throw new Error("OpenCode client does not expose session.prompt or session.promptAsync.");
|
|
9609
9609
|
}
|
|
9610
|
+
function normalizeOpenCodeSessionMessages(result) {
|
|
9611
|
+
const data = result?.data ?? result;
|
|
9612
|
+
if (Array.isArray(data)) return [...data];
|
|
9613
|
+
if (Array.isArray(data?.messages)) return [...data.messages];
|
|
9614
|
+
if (Array.isArray(data?.items)) return [...data.items];
|
|
9615
|
+
return [];
|
|
9616
|
+
}
|
|
9617
|
+
async function readOpenCodeSessionMessages(client, { sessionId, limit = 20 } = {}) {
|
|
9618
|
+
if (typeof client?.session?.messages !== "function") return null;
|
|
9619
|
+
const attempts = [
|
|
9620
|
+
{ path: { id: sessionId }, query: { limit } },
|
|
9621
|
+
{ path: { sessionID: sessionId }, query: { limit } },
|
|
9622
|
+
{ id: sessionId, limit },
|
|
9623
|
+
{ sessionID: sessionId, limit }
|
|
9624
|
+
];
|
|
9625
|
+
let firstError = null;
|
|
9626
|
+
for (const attempt of attempts) {
|
|
9627
|
+
try {
|
|
9628
|
+
return normalizeOpenCodeSessionMessages(await client.session.messages(attempt));
|
|
9629
|
+
} catch (error) {
|
|
9630
|
+
firstError ??= error;
|
|
9631
|
+
}
|
|
9632
|
+
}
|
|
9633
|
+
throw firstError;
|
|
9634
|
+
}
|
|
9635
|
+
function openCodeMessageText(message) {
|
|
9636
|
+
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
9637
|
+
const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
|
|
9638
|
+
for (const part of partList) parts.push(part?.text, part?.content);
|
|
9639
|
+
return parts.filter((value) => typeof value === "string").join("\n");
|
|
9640
|
+
}
|
|
9641
|
+
async function verifyOpenCodeSessionEventDelivery(client, { sessionId, beforeMessages = null, expectedText = "", markers = [], attempts = 3, delayMs = 25 } = {}) {
|
|
9642
|
+
let lastError = "message_verification_unavailable";
|
|
9643
|
+
for (let attempt = 0; attempt < Math.max(1, attempts); attempt += 1) {
|
|
9644
|
+
try {
|
|
9645
|
+
const afterMessages = await readOpenCodeSessionMessages(client, { sessionId, limit: 50 });
|
|
9646
|
+
if (!afterMessages) return { ok: true, method: "verification_unavailable", skipped: true };
|
|
9647
|
+
const beforeCount = Array.isArray(beforeMessages) ? beforeMessages.length : null;
|
|
9648
|
+
if (beforeCount !== null && afterMessages.length > beforeCount) return { ok: true, method: "message_count", beforeCount, afterCount: afterMessages.length };
|
|
9649
|
+
const textNeedles = [expectedText, ...markers].map((value) => String(value || "").trim()).filter(Boolean);
|
|
9650
|
+
const haystack = afterMessages.slice(-20).map(openCodeMessageText).join("\n");
|
|
9651
|
+
const matched = textNeedles.find((needle) => haystack.includes(needle));
|
|
9652
|
+
if (matched) return { ok: true, method: "message_text", marker: matched, beforeCount, afterCount: afterMessages.length };
|
|
9653
|
+
lastError = "message_not_visible";
|
|
9654
|
+
} catch (error) {
|
|
9655
|
+
lastError = error.message || "message_verification_failed";
|
|
9656
|
+
}
|
|
9657
|
+
if (attempt < attempts - 1 && delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
9658
|
+
}
|
|
9659
|
+
return { ok: false, reason: lastError };
|
|
9660
|
+
}
|
|
9661
|
+
function buildClickUpMessageDeliveryBlockerComment({ taskId, sessionId, reason, action } = {}) {
|
|
9662
|
+
return [
|
|
9663
|
+
`Optima blocker: could not deliver ClickUp task ${taskId} to OpenCode session ${sessionId}.`,
|
|
9664
|
+
`Delivery verification failed after send${action ? ` (${action})` : ""}: ${reason || "message_delivery_failed"}.`,
|
|
9665
|
+
"The webhook did not mark this event as successfully routed; please inspect/replay the event or route the task manually.",
|
|
9666
|
+
clickUpNoAbandonmentRuleText()
|
|
9667
|
+
].join("\n");
|
|
9668
|
+
}
|
|
9669
|
+
async function postClickUpMessageDeliveryBlocker({ clickupClient, worktree, taskId, sessionId, reason, action } = {}) {
|
|
9670
|
+
const comment = buildClickUpMessageDeliveryBlockerComment({ taskId, sessionId, reason, action });
|
|
9671
|
+
if (typeof clickupClient?.postTaskComment !== "function") {
|
|
9672
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_blocker_comment_unavailable", taskId, sessionId, reason, action });
|
|
9673
|
+
return { ok: false, skipped: true, reason: "post_task_comment_unavailable", comment };
|
|
9674
|
+
}
|
|
9675
|
+
try {
|
|
9676
|
+
await clickupClient.postTaskComment({ taskId, comment });
|
|
9677
|
+
return { ok: true, comment };
|
|
9678
|
+
} catch (error) {
|
|
9679
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_blocker_comment_failed", taskId, sessionId, reason, action, message: error.message });
|
|
9680
|
+
return { ok: false, error: error.message, comment };
|
|
9681
|
+
}
|
|
9682
|
+
}
|
|
9683
|
+
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery } = {}) {
|
|
9684
|
+
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => null);
|
|
9685
|
+
await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl });
|
|
9686
|
+
let verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages, expectedText: text, markers: eventMarkers });
|
|
9687
|
+
if (verification?.ok) return { ok: true, verification, fallback: false };
|
|
9688
|
+
const canFallbackDirect = Boolean(opencodeBaseUrl);
|
|
9689
|
+
if (canFallbackDirect) {
|
|
9690
|
+
const retryBeforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, limit: 50 }).catch(() => beforeMessages);
|
|
9691
|
+
await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: true });
|
|
9692
|
+
verification = await verifySessionEventDelivery(openCodeClient, { sessionId, beforeMessages: retryBeforeMessages, expectedText: text, markers: eventMarkers });
|
|
9693
|
+
if (verification?.ok) return { ok: true, verification, fallback: true };
|
|
9694
|
+
}
|
|
9695
|
+
const reason = verification?.reason || "message_delivery_failed";
|
|
9696
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: canFallbackDirect });
|
|
9697
|
+
const blocker = await postClickUpMessageDeliveryBlocker({ clickupClient, worktree, taskId, sessionId, reason, action: canFallbackDirect ? "fallback_failed" : "verification_failed" });
|
|
9698
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: canFallbackDirect, blockerComment: blocker };
|
|
9699
|
+
}
|
|
9610
9700
|
function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", worktree = "", deliveryEvidencePath = "" }) {
|
|
9611
9701
|
const comment = clickUpCommentFromPayload(payload);
|
|
9612
9702
|
const commentText = clickUpCommentText(comment).trim();
|
|
@@ -9838,7 +9928,7 @@ async function withClickUpTaskRouteLock(taskId, operation) {
|
|
|
9838
9928
|
if (activeClickUpTaskRoutes.get(key) === current) activeClickUpTaskRoutes.delete(key);
|
|
9839
9929
|
}
|
|
9840
9930
|
}
|
|
9841
|
-
async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktree, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
|
|
9931
|
+
async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktree, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
|
|
9842
9932
|
const eventType = clickUpEventType(payload);
|
|
9843
9933
|
const eventKey = clickUpWebhookEventKey(payload);
|
|
9844
9934
|
const remembered = rememberClickUpWebhookEvent(state, eventKey);
|
|
@@ -9928,18 +10018,20 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
9928
10018
|
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_metadata_failed", taskId, sessionId: pendingSessionId, message: error.message });
|
|
9929
10019
|
throw error;
|
|
9930
10020
|
}
|
|
9931
|
-
await
|
|
10021
|
+
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId: pendingSessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
10022
|
+
if (!delivery.ok) return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
9932
10023
|
const nextMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(pendingMetadata, config.routing.metadataKey, pendingSessionId), config.routing.metadataKey);
|
|
9933
10024
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: nextMetadata });
|
|
9934
10025
|
const { [taskId]: _completedPending, ...remainingPending } = stateToPersist.pendingSessions || {};
|
|
9935
10026
|
stateToPersist = { ...stateToPersist, pendingSessions: remainingPending };
|
|
9936
|
-
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
10027
|
+
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryFallback: delivery.fallback });
|
|
9937
10028
|
}
|
|
9938
10029
|
const sessionId = String(existingSessionId);
|
|
9939
10030
|
if (await sessionExists(openCodeClient, sessionId)) {
|
|
9940
10031
|
if (typeof clickupClient?.updateTaskMetadata === "function") await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: metadataWithRouting });
|
|
9941
|
-
await
|
|
9942
|
-
return finish({
|
|
10032
|
+
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
10033
|
+
if (!delivery.ok) return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path });
|
|
10034
|
+
return finish({ ok: true, action: "sent_to_existing_session", taskId, sessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryFallback: delivery.fallback });
|
|
9943
10035
|
}
|
|
9944
10036
|
const at = now().toISOString();
|
|
9945
10037
|
const incidentComment = `Optima webhook could not route this ClickUp event because OpenCode session ${sessionId} is missing on host ${host} at ${at}. No replacement session was created automatically.`;
|
|
@@ -11834,7 +11926,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
11834
11926
|
}
|
|
11835
11927
|
};
|
|
11836
11928
|
}
|
|
11837
|
-
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, readClickUpCommentLedger, readClickUpWebhookState, reconcileClickUpStartup, recordClickUpCommentVersionProcessed, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
11929
|
+
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, readClickUpCommentLedger, readClickUpWebhookState, reconcileClickUpStartup, recordClickUpCommentVersionProcessed, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
11838
11930
|
|
|
11839
11931
|
// src/sanitize_cli.js
|
|
11840
11932
|
var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
|