@defend-tech/opencode-optima 0.1.12 → 0.1.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 +116 -18
- package/dist/sanitize_cli.js +116 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7929,6 +7929,8 @@ var CLICKUP_PM_MENTION_NAME = "Defend Tech Product Manager";
|
|
|
7929
7929
|
var CLICKUP_WEBHOOK_RUNTIME_VERSION = 1;
|
|
7930
7930
|
var CLICKUP_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
7931
7931
|
var CLICKUP_WEBHOOK_REQUEST_TIMEOUT_MS = 1e4;
|
|
7932
|
+
var CLICKUP_WEBHOOK_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "info", "verbose"]);
|
|
7933
|
+
var CLICKUP_WEBHOOK_REDACTED = "[REDACTED]";
|
|
7932
7934
|
var DISCUSSION_BACKFILL_FETCH_LIMIT = 100;
|
|
7933
7935
|
var DEFAULT_PRESERVE_EXISTING_AGENTS = true;
|
|
7934
7936
|
var SAFE_WORKTREE_FAILURE = "FAIL: Optima needs a writable project directory. Open/add a project in OpenChamber first. Refusing to use '/'.";
|
|
@@ -8793,6 +8795,22 @@ function clickUpWebhookStatePath(worktree) {
|
|
|
8793
8795
|
function clickUpWebhookLogPath(worktree) {
|
|
8794
8796
|
return path2.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
|
|
8795
8797
|
}
|
|
8798
|
+
function normalizeClickUpWebhookLogLevel(value) {
|
|
8799
|
+
const level = String(value || "info").trim().toLowerCase();
|
|
8800
|
+
return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
|
|
8801
|
+
}
|
|
8802
|
+
function clickUpWebhookAuditLogDir() {
|
|
8803
|
+
const dataHome = process.env.XDG_DATA_HOME && path2.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path2.join(os.homedir(), ".local", "share", "opencode");
|
|
8804
|
+
return path2.join(dataHome, "opencode-optima");
|
|
8805
|
+
}
|
|
8806
|
+
function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
8807
|
+
return path2.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
|
|
8808
|
+
}
|
|
8809
|
+
function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
8810
|
+
const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
|
|
8811
|
+
const shortId = crypto.randomBytes(4).toString("hex");
|
|
8812
|
+
return path2.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
|
|
8813
|
+
}
|
|
8796
8814
|
function findOptimaPluginTupleOptions(pluginEntries = []) {
|
|
8797
8815
|
if (!Array.isArray(pluginEntries)) return null;
|
|
8798
8816
|
for (const entry of pluginEntries) {
|
|
@@ -8822,6 +8840,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
8822
8840
|
basePath: String(raw.base_path || raw.basePath || worktree || "").trim(),
|
|
8823
8841
|
teamId: String(raw.team_id || raw.teamId || "").trim(),
|
|
8824
8842
|
apiToken: String(raw.api_token || raw.apiToken || "").trim(),
|
|
8843
|
+
log: normalizeClickUpWebhookLogLevel(raw.log),
|
|
8825
8844
|
webhook: {
|
|
8826
8845
|
publicUrl: String(webhook.public_url || webhook.publicUrl || "").trim(),
|
|
8827
8846
|
bindHost: String(webhook.bind_host || webhook.bindHost || "127.0.0.1").trim(),
|
|
@@ -9212,6 +9231,74 @@ function appendClickUpWebhookLocalLog(worktree, entry) {
|
|
|
9212
9231
|
fs2.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
|
|
9213
9232
|
`, "utf8");
|
|
9214
9233
|
}
|
|
9234
|
+
function redactClickUpWebhookAuditValue(value, secretValues = []) {
|
|
9235
|
+
if (typeof value === "string") {
|
|
9236
|
+
return secretValues.reduce((next, secret) => secret ? next.split(secret).join(CLICKUP_WEBHOOK_REDACTED) : next, value);
|
|
9237
|
+
}
|
|
9238
|
+
if (Array.isArray(value)) return value.map((item) => redactClickUpWebhookAuditValue(item, secretValues));
|
|
9239
|
+
if (!isPlainObject(value)) return value;
|
|
9240
|
+
return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => {
|
|
9241
|
+
const normalizedKey = normalizeLooseToken(key);
|
|
9242
|
+
const secretKey = normalizedKey.includes("signature") || normalizedKey.includes("authorization") || normalizedKey.includes("cookie") || normalizedKey.includes("token") || normalizedKey.includes("secret") || normalizedKey.includes("api-key") || normalizedKey.includes("apikey");
|
|
9243
|
+
return [key, secretKey ? CLICKUP_WEBHOOK_REDACTED : redactClickUpWebhookAuditValue(entryValue, secretValues)];
|
|
9244
|
+
}));
|
|
9245
|
+
}
|
|
9246
|
+
function buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at = /* @__PURE__ */ new Date() } = {}) {
|
|
9247
|
+
const result = handled?.result || {};
|
|
9248
|
+
const summary = {
|
|
9249
|
+
at: at.toISOString(),
|
|
9250
|
+
method,
|
|
9251
|
+
path: url === null ? null : new URL(String(url || "/"), config?.webhook?.publicUrl || "http://localhost").pathname,
|
|
9252
|
+
status: handled?.status || 500,
|
|
9253
|
+
ok: Boolean(handled?.ok),
|
|
9254
|
+
reason: handled?.reason || result.reason || (error ? "handler_error" : void 0),
|
|
9255
|
+
action: result.action,
|
|
9256
|
+
event: payload ? clickUpEventType(payload) : void 0,
|
|
9257
|
+
task: result.taskId || clickUpTaskIdFromPayload(payload || {}),
|
|
9258
|
+
comment: clickUpCommentFromPayload(payload || {})?.id || payload?.comment_id || payload?.commentId,
|
|
9259
|
+
session: result.sessionId,
|
|
9260
|
+
base_path: config?.basePath || "",
|
|
9261
|
+
request_file: requestFile || void 0
|
|
9262
|
+
};
|
|
9263
|
+
return Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== void 0 && value !== ""));
|
|
9264
|
+
}
|
|
9265
|
+
function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "", config, state = {}, handled = null, error = null, payload = null, at = /* @__PURE__ */ new Date() } = {}) {
|
|
9266
|
+
try {
|
|
9267
|
+
const level = normalizeClickUpWebhookLogLevel(config?.log);
|
|
9268
|
+
const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
|
|
9269
|
+
if (level === "error" && !failed) return;
|
|
9270
|
+
const logDir = clickUpWebhookAuditLogDir();
|
|
9271
|
+
fs2.mkdirSync(logDir, { recursive: true });
|
|
9272
|
+
const secretValues = [resolveSecretReference(config?.apiToken), state?.secret, config?.webhook?.secret].filter(Boolean);
|
|
9273
|
+
let requestFile;
|
|
9274
|
+
if (level === "verbose") {
|
|
9275
|
+
const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
|
|
9276
|
+
fs2.mkdirSync(path2.dirname(absoluteRequestFile), { recursive: true });
|
|
9277
|
+
requestFile = path2.relative(logDir, absoluteRequestFile).split(path2.sep).join("/");
|
|
9278
|
+
const parsedBody = payload || (() => {
|
|
9279
|
+
try {
|
|
9280
|
+
return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
|
|
9281
|
+
} catch {
|
|
9282
|
+
return void 0;
|
|
9283
|
+
}
|
|
9284
|
+
})();
|
|
9285
|
+
const requestArtifact = redactClickUpWebhookAuditValue({
|
|
9286
|
+
at: at.toISOString(),
|
|
9287
|
+
method,
|
|
9288
|
+
url,
|
|
9289
|
+
path: url === null ? null : new URL(String(url || "/"), config?.webhook?.publicUrl || "http://localhost").pathname,
|
|
9290
|
+
headers,
|
|
9291
|
+
body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
|
|
9292
|
+
}, secretValues);
|
|
9293
|
+
fs2.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
|
|
9294
|
+
`, "utf8");
|
|
9295
|
+
}
|
|
9296
|
+
const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
|
|
9297
|
+
fs2.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
|
|
9298
|
+
`, "utf8");
|
|
9299
|
+
} catch {
|
|
9300
|
+
}
|
|
9301
|
+
}
|
|
9215
9302
|
async function withClickUpTaskRouteLock(taskId, operation) {
|
|
9216
9303
|
const key = String(taskId || "");
|
|
9217
9304
|
if (!key) return operation();
|
|
@@ -9309,25 +9396,36 @@ function clickUpWebhookExpectedPath(config) {
|
|
|
9309
9396
|
return "/";
|
|
9310
9397
|
}
|
|
9311
9398
|
}
|
|
9312
|
-
async function handleClickUpWebhookRequest({ method = "POST", url = null, headers = {}, rawBody = "", config, state, worktree, clickupClient, openCodeClient, saveState } = {}) {
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
if (bodyBytes > maxBodyBytes) return { ok: false, status: 413, reason: "body_too_large" };
|
|
9321
|
-
const signature = headers["x-signature"] || headers["X-Signature"];
|
|
9322
|
-
if (!verifyClickUpSignature(rawBody, signature, state?.secret)) return { ok: false, status: 401, reason: "invalid_signature" };
|
|
9323
|
-
let payload;
|
|
9399
|
+
async function handleClickUpWebhookRequest({ method = "POST", url = null, headers = {}, rawBody = "", config, state, worktree, clickupClient, openCodeClient, saveState, now = () => /* @__PURE__ */ new Date() } = {}) {
|
|
9400
|
+
let payload = null;
|
|
9401
|
+
let handled = null;
|
|
9402
|
+
const finish = (result) => {
|
|
9403
|
+
handled = result;
|
|
9404
|
+
writeClickUpWebhookAuditLog({ method, url, headers, rawBody, config, state, handled, payload, at: now() });
|
|
9405
|
+
return result;
|
|
9406
|
+
};
|
|
9324
9407
|
try {
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9408
|
+
if (method !== "POST") return finish({ ok: false, status: 405, reason: "method_not_allowed" });
|
|
9409
|
+
if (url !== null) {
|
|
9410
|
+
const requestPath = new URL(String(url), config?.webhook?.publicUrl || "http://localhost").pathname;
|
|
9411
|
+
if (requestPath !== clickUpWebhookExpectedPath(config)) return finish({ ok: false, status: 404, reason: "wrong_path" });
|
|
9412
|
+
}
|
|
9413
|
+
const maxBodyBytes = Number(config?.webhook?.maxBodyBytes || CLICKUP_WEBHOOK_MAX_BODY_BYTES);
|
|
9414
|
+
const bodyBytes = Buffer.isBuffer(rawBody) ? rawBody.length : Buffer.byteLength(String(rawBody || ""));
|
|
9415
|
+
if (bodyBytes > maxBodyBytes) return finish({ ok: false, status: 413, reason: "body_too_large" });
|
|
9416
|
+
const signature = headers["x-signature"] || headers["X-Signature"];
|
|
9417
|
+
if (!verifyClickUpSignature(rawBody, signature, state?.secret)) return finish({ ok: false, status: 401, reason: "invalid_signature" });
|
|
9418
|
+
try {
|
|
9419
|
+
payload = JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody));
|
|
9420
|
+
} catch {
|
|
9421
|
+
return finish({ ok: false, status: 400, reason: "invalid_json" });
|
|
9422
|
+
}
|
|
9423
|
+
const result = await routeClickUpWebhookEvent({ payload, config, state, worktree, clickupClient, openCodeClient, saveState });
|
|
9424
|
+
return finish({ ok: result.ok, status: result.ok ? 200 : 422, result });
|
|
9425
|
+
} catch (error) {
|
|
9426
|
+
writeClickUpWebhookAuditLog({ method, url, headers, rawBody, config, state, handled, error, payload, at: now() });
|
|
9427
|
+
throw error;
|
|
9328
9428
|
}
|
|
9329
|
-
const result = await routeClickUpWebhookEvent({ payload, config, state, worktree, clickupClient, openCodeClient, saveState });
|
|
9330
|
-
return { ok: result.ok, status: result.ok ? 200 : 422, result };
|
|
9331
9429
|
}
|
|
9332
9430
|
function clickUpListenerKey(config) {
|
|
9333
9431
|
return `${config?.webhook?.bindHost || "127.0.0.1"}:${config?.webhook?.bindPort || 0}`;
|
|
@@ -11019,7 +11117,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
11019
11117
|
}
|
|
11020
11118
|
};
|
|
11021
11119
|
}
|
|
11022
|
-
OptimaPlugin.__internals = { buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentMentionsProductManager, createClickUpApiClient, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, readClickUpWebhookState, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, 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 };
|
|
11120
|
+
OptimaPlugin.__internals = { buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, readClickUpWebhookState, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, 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 };
|
|
11023
11121
|
export {
|
|
11024
11122
|
OptimaPlugin as default
|
|
11025
11123
|
};
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -7936,6 +7936,8 @@ var CLICKUP_PM_MENTION_NAME = "Defend Tech Product Manager";
|
|
|
7936
7936
|
var CLICKUP_WEBHOOK_RUNTIME_VERSION = 1;
|
|
7937
7937
|
var CLICKUP_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
7938
7938
|
var CLICKUP_WEBHOOK_REQUEST_TIMEOUT_MS = 1e4;
|
|
7939
|
+
var CLICKUP_WEBHOOK_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "info", "verbose"]);
|
|
7940
|
+
var CLICKUP_WEBHOOK_REDACTED = "[REDACTED]";
|
|
7939
7941
|
var DISCUSSION_BACKFILL_FETCH_LIMIT = 100;
|
|
7940
7942
|
var DEFAULT_PRESERVE_EXISTING_AGENTS = true;
|
|
7941
7943
|
var SAFE_WORKTREE_FAILURE = "FAIL: Optima needs a writable project directory. Open/add a project in OpenChamber first. Refusing to use '/'.";
|
|
@@ -8800,6 +8802,22 @@ function clickUpWebhookStatePath(worktree) {
|
|
|
8800
8802
|
function clickUpWebhookLogPath(worktree) {
|
|
8801
8803
|
return path2.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
|
|
8802
8804
|
}
|
|
8805
|
+
function normalizeClickUpWebhookLogLevel(value) {
|
|
8806
|
+
const level = String(value || "info").trim().toLowerCase();
|
|
8807
|
+
return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
|
|
8808
|
+
}
|
|
8809
|
+
function clickUpWebhookAuditLogDir() {
|
|
8810
|
+
const dataHome = process.env.XDG_DATA_HOME && path2.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path2.join(os.homedir(), ".local", "share", "opencode");
|
|
8811
|
+
return path2.join(dataHome, "opencode-optima");
|
|
8812
|
+
}
|
|
8813
|
+
function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
8814
|
+
return path2.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
|
|
8815
|
+
}
|
|
8816
|
+
function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
8817
|
+
const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
|
|
8818
|
+
const shortId = crypto.randomBytes(4).toString("hex");
|
|
8819
|
+
return path2.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
|
|
8820
|
+
}
|
|
8803
8821
|
function findOptimaPluginTupleOptions(pluginEntries = []) {
|
|
8804
8822
|
if (!Array.isArray(pluginEntries)) return null;
|
|
8805
8823
|
for (const entry of pluginEntries) {
|
|
@@ -8829,6 +8847,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
8829
8847
|
basePath: String(raw.base_path || raw.basePath || worktree || "").trim(),
|
|
8830
8848
|
teamId: String(raw.team_id || raw.teamId || "").trim(),
|
|
8831
8849
|
apiToken: String(raw.api_token || raw.apiToken || "").trim(),
|
|
8850
|
+
log: normalizeClickUpWebhookLogLevel(raw.log),
|
|
8832
8851
|
webhook: {
|
|
8833
8852
|
publicUrl: String(webhook.public_url || webhook.publicUrl || "").trim(),
|
|
8834
8853
|
bindHost: String(webhook.bind_host || webhook.bindHost || "127.0.0.1").trim(),
|
|
@@ -9219,6 +9238,74 @@ function appendClickUpWebhookLocalLog(worktree, entry) {
|
|
|
9219
9238
|
fs2.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
|
|
9220
9239
|
`, "utf8");
|
|
9221
9240
|
}
|
|
9241
|
+
function redactClickUpWebhookAuditValue(value, secretValues = []) {
|
|
9242
|
+
if (typeof value === "string") {
|
|
9243
|
+
return secretValues.reduce((next, secret) => secret ? next.split(secret).join(CLICKUP_WEBHOOK_REDACTED) : next, value);
|
|
9244
|
+
}
|
|
9245
|
+
if (Array.isArray(value)) return value.map((item) => redactClickUpWebhookAuditValue(item, secretValues));
|
|
9246
|
+
if (!isPlainObject(value)) return value;
|
|
9247
|
+
return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => {
|
|
9248
|
+
const normalizedKey = normalizeLooseToken(key);
|
|
9249
|
+
const secretKey = normalizedKey.includes("signature") || normalizedKey.includes("authorization") || normalizedKey.includes("cookie") || normalizedKey.includes("token") || normalizedKey.includes("secret") || normalizedKey.includes("api-key") || normalizedKey.includes("apikey");
|
|
9250
|
+
return [key, secretKey ? CLICKUP_WEBHOOK_REDACTED : redactClickUpWebhookAuditValue(entryValue, secretValues)];
|
|
9251
|
+
}));
|
|
9252
|
+
}
|
|
9253
|
+
function buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at = /* @__PURE__ */ new Date() } = {}) {
|
|
9254
|
+
const result = handled?.result || {};
|
|
9255
|
+
const summary = {
|
|
9256
|
+
at: at.toISOString(),
|
|
9257
|
+
method,
|
|
9258
|
+
path: url === null ? null : new URL(String(url || "/"), config?.webhook?.publicUrl || "http://localhost").pathname,
|
|
9259
|
+
status: handled?.status || 500,
|
|
9260
|
+
ok: Boolean(handled?.ok),
|
|
9261
|
+
reason: handled?.reason || result.reason || (error ? "handler_error" : void 0),
|
|
9262
|
+
action: result.action,
|
|
9263
|
+
event: payload ? clickUpEventType(payload) : void 0,
|
|
9264
|
+
task: result.taskId || clickUpTaskIdFromPayload(payload || {}),
|
|
9265
|
+
comment: clickUpCommentFromPayload(payload || {})?.id || payload?.comment_id || payload?.commentId,
|
|
9266
|
+
session: result.sessionId,
|
|
9267
|
+
base_path: config?.basePath || "",
|
|
9268
|
+
request_file: requestFile || void 0
|
|
9269
|
+
};
|
|
9270
|
+
return Object.fromEntries(Object.entries(summary).filter(([, value]) => value !== void 0 && value !== ""));
|
|
9271
|
+
}
|
|
9272
|
+
function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "", config, state = {}, handled = null, error = null, payload = null, at = /* @__PURE__ */ new Date() } = {}) {
|
|
9273
|
+
try {
|
|
9274
|
+
const level = normalizeClickUpWebhookLogLevel(config?.log);
|
|
9275
|
+
const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
|
|
9276
|
+
if (level === "error" && !failed) return;
|
|
9277
|
+
const logDir = clickUpWebhookAuditLogDir();
|
|
9278
|
+
fs2.mkdirSync(logDir, { recursive: true });
|
|
9279
|
+
const secretValues = [resolveSecretReference(config?.apiToken), state?.secret, config?.webhook?.secret].filter(Boolean);
|
|
9280
|
+
let requestFile;
|
|
9281
|
+
if (level === "verbose") {
|
|
9282
|
+
const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
|
|
9283
|
+
fs2.mkdirSync(path2.dirname(absoluteRequestFile), { recursive: true });
|
|
9284
|
+
requestFile = path2.relative(logDir, absoluteRequestFile).split(path2.sep).join("/");
|
|
9285
|
+
const parsedBody = payload || (() => {
|
|
9286
|
+
try {
|
|
9287
|
+
return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
|
|
9288
|
+
} catch {
|
|
9289
|
+
return void 0;
|
|
9290
|
+
}
|
|
9291
|
+
})();
|
|
9292
|
+
const requestArtifact = redactClickUpWebhookAuditValue({
|
|
9293
|
+
at: at.toISOString(),
|
|
9294
|
+
method,
|
|
9295
|
+
url,
|
|
9296
|
+
path: url === null ? null : new URL(String(url || "/"), config?.webhook?.publicUrl || "http://localhost").pathname,
|
|
9297
|
+
headers,
|
|
9298
|
+
body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
|
|
9299
|
+
}, secretValues);
|
|
9300
|
+
fs2.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
|
|
9301
|
+
`, "utf8");
|
|
9302
|
+
}
|
|
9303
|
+
const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
|
|
9304
|
+
fs2.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
|
|
9305
|
+
`, "utf8");
|
|
9306
|
+
} catch {
|
|
9307
|
+
}
|
|
9308
|
+
}
|
|
9222
9309
|
async function withClickUpTaskRouteLock(taskId, operation) {
|
|
9223
9310
|
const key = String(taskId || "");
|
|
9224
9311
|
if (!key) return operation();
|
|
@@ -9316,25 +9403,36 @@ function clickUpWebhookExpectedPath(config) {
|
|
|
9316
9403
|
return "/";
|
|
9317
9404
|
}
|
|
9318
9405
|
}
|
|
9319
|
-
async function handleClickUpWebhookRequest({ method = "POST", url = null, headers = {}, rawBody = "", config, state, worktree, clickupClient, openCodeClient, saveState } = {}) {
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
if (bodyBytes > maxBodyBytes) return { ok: false, status: 413, reason: "body_too_large" };
|
|
9328
|
-
const signature = headers["x-signature"] || headers["X-Signature"];
|
|
9329
|
-
if (!verifyClickUpSignature(rawBody, signature, state?.secret)) return { ok: false, status: 401, reason: "invalid_signature" };
|
|
9330
|
-
let payload;
|
|
9406
|
+
async function handleClickUpWebhookRequest({ method = "POST", url = null, headers = {}, rawBody = "", config, state, worktree, clickupClient, openCodeClient, saveState, now = () => /* @__PURE__ */ new Date() } = {}) {
|
|
9407
|
+
let payload = null;
|
|
9408
|
+
let handled = null;
|
|
9409
|
+
const finish = (result) => {
|
|
9410
|
+
handled = result;
|
|
9411
|
+
writeClickUpWebhookAuditLog({ method, url, headers, rawBody, config, state, handled, payload, at: now() });
|
|
9412
|
+
return result;
|
|
9413
|
+
};
|
|
9331
9414
|
try {
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9415
|
+
if (method !== "POST") return finish({ ok: false, status: 405, reason: "method_not_allowed" });
|
|
9416
|
+
if (url !== null) {
|
|
9417
|
+
const requestPath = new URL(String(url), config?.webhook?.publicUrl || "http://localhost").pathname;
|
|
9418
|
+
if (requestPath !== clickUpWebhookExpectedPath(config)) return finish({ ok: false, status: 404, reason: "wrong_path" });
|
|
9419
|
+
}
|
|
9420
|
+
const maxBodyBytes = Number(config?.webhook?.maxBodyBytes || CLICKUP_WEBHOOK_MAX_BODY_BYTES);
|
|
9421
|
+
const bodyBytes = Buffer.isBuffer(rawBody) ? rawBody.length : Buffer.byteLength(String(rawBody || ""));
|
|
9422
|
+
if (bodyBytes > maxBodyBytes) return finish({ ok: false, status: 413, reason: "body_too_large" });
|
|
9423
|
+
const signature = headers["x-signature"] || headers["X-Signature"];
|
|
9424
|
+
if (!verifyClickUpSignature(rawBody, signature, state?.secret)) return finish({ ok: false, status: 401, reason: "invalid_signature" });
|
|
9425
|
+
try {
|
|
9426
|
+
payload = JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody));
|
|
9427
|
+
} catch {
|
|
9428
|
+
return finish({ ok: false, status: 400, reason: "invalid_json" });
|
|
9429
|
+
}
|
|
9430
|
+
const result = await routeClickUpWebhookEvent({ payload, config, state, worktree, clickupClient, openCodeClient, saveState });
|
|
9431
|
+
return finish({ ok: result.ok, status: result.ok ? 200 : 422, result });
|
|
9432
|
+
} catch (error) {
|
|
9433
|
+
writeClickUpWebhookAuditLog({ method, url, headers, rawBody, config, state, handled, error, payload, at: now() });
|
|
9434
|
+
throw error;
|
|
9335
9435
|
}
|
|
9336
|
-
const result = await routeClickUpWebhookEvent({ payload, config, state, worktree, clickupClient, openCodeClient, saveState });
|
|
9337
|
-
return { ok: result.ok, status: result.ok ? 200 : 422, result };
|
|
9338
9436
|
}
|
|
9339
9437
|
function clickUpListenerKey(config) {
|
|
9340
9438
|
return `${config?.webhook?.bindHost || "127.0.0.1"}:${config?.webhook?.bindPort || 0}`;
|
|
@@ -11026,7 +11124,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
11026
11124
|
}
|
|
11027
11125
|
};
|
|
11028
11126
|
}
|
|
11029
|
-
OptimaPlugin.__internals = { buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentMentionsProductManager, createClickUpApiClient, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, readClickUpWebhookState, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, 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 };
|
|
11127
|
+
OptimaPlugin.__internals = { buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, readClickUpWebhookState, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, 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 };
|
|
11030
11128
|
|
|
11031
11129
|
// src/sanitize_cli.js
|
|
11032
11130
|
var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
|