@defend-tech/opencode-optima 0.1.53 → 0.1.55
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 +286 -11
- package/dist/sanitize_cli.js +286 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9256,17 +9256,20 @@ function clickUpWebhookLocationCompatible(webhook = {}, config = {}) {
|
|
|
9256
9256
|
}
|
|
9257
9257
|
return true;
|
|
9258
9258
|
}
|
|
9259
|
-
async function findReusableClickUpWebhook(config, clickupClient = null) {
|
|
9259
|
+
async function findReusableClickUpWebhook(config, clickupClient = null, existingState = null) {
|
|
9260
9260
|
if (!clickupClient?.listWebhooks) return null;
|
|
9261
9261
|
const listed = await clickupClient.listWebhooks({ teamId: config.teamId });
|
|
9262
|
+
let secretlessMatch = null;
|
|
9262
9263
|
for (const webhook of clickUpWebhookListItems(listed)) {
|
|
9263
9264
|
const remote = normalizeClickUpWebhookApiResponse(webhook, config);
|
|
9264
9265
|
if (remote.publicUrl !== config.webhook.publicUrl) continue;
|
|
9265
9266
|
if (!clickUpWebhookLocationCompatible(webhook, config)) continue;
|
|
9266
|
-
|
|
9267
|
-
|
|
9267
|
+
const existingSecret = existingState?.webhookId === remote.webhookId ? existingState.secret : "";
|
|
9268
|
+
const reusable = remote.secret ? remote : { ...remote, secret: existingSecret };
|
|
9269
|
+
if (isClickUpWebhookStateActive(reusable, config)) return reusable;
|
|
9270
|
+
if (remote.webhookId && !secretlessMatch) secretlessMatch = { ...remote, active: false, reason: "remote_secret_unavailable" };
|
|
9268
9271
|
}
|
|
9269
|
-
return
|
|
9272
|
+
return secretlessMatch;
|
|
9270
9273
|
}
|
|
9271
9274
|
async function validateClickUpWebhookState(state, config, clickupClient = null, { allowRemoteUnhealthyLocalRecovery = false } = {}) {
|
|
9272
9275
|
if (!isClickUpWebhookStateActive(state, config)) return { valid: false, reason: "state_incomplete" };
|
|
@@ -9311,11 +9314,16 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
|
|
|
9311
9314
|
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: existingValidation.mode });
|
|
9312
9315
|
return { active: true, valid: true, mode: existingValidation.mode, limitation: existingValidation.limitation, state };
|
|
9313
9316
|
}
|
|
9314
|
-
const reusableRemote = await findReusableClickUpWebhook(config, clickupClient);
|
|
9317
|
+
const reusableRemote = await findReusableClickUpWebhook(config, clickupClient, existing);
|
|
9315
9318
|
if (reusableRemote) {
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
+
if (isClickUpWebhookStateActive(reusableRemote, config)) {
|
|
9320
|
+
const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
|
|
9321
|
+
const mode2 = reusableRemote.secret === existing.secret && existing.webhookId === reusableRemote.webhookId ? "remote_discovered_local_secret" : "remote_discovered";
|
|
9322
|
+
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: mode2 });
|
|
9323
|
+
return { active: true, valid: true, mode: mode2, state };
|
|
9324
|
+
}
|
|
9325
|
+
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_preserved", webhookId: reusableRemote.webhookId, reason: reusableRemote.reason || "remote_webhook_exists_without_secret" });
|
|
9326
|
+
return { active: false, valid: false, reason: reusableRemote.reason || "remote_webhook_exists_without_secret", state: existing, remote: reusableRemote };
|
|
9319
9327
|
}
|
|
9320
9328
|
if (existing.webhookId && clickupClient?.deleteWebhook) {
|
|
9321
9329
|
await deleteClickUpWebhookBestEffort({ webhookId: existing.webhookId, clickupClient, worktree, reason: existingValidation.reason || "startup_self_heal" });
|
|
@@ -9822,12 +9830,170 @@ function normalizeOpenCodeSessionMessages(result) {
|
|
|
9822
9830
|
if (Array.isArray(data?.items)) return [...data.items];
|
|
9823
9831
|
return [];
|
|
9824
9832
|
}
|
|
9833
|
+
function clampOpenCodeMessageLimit(limit) {
|
|
9834
|
+
const value = Number(limit);
|
|
9835
|
+
if (!Number.isFinite(value)) return 20;
|
|
9836
|
+
return Math.min(50, Math.max(1, Math.floor(value)));
|
|
9837
|
+
}
|
|
9838
|
+
function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
|
|
9839
|
+
const value = String(text ?? "");
|
|
9840
|
+
return value.length > maxLength ? value.slice(0, maxLength) : value;
|
|
9841
|
+
}
|
|
9842
|
+
function hashOpenCodeSessionText(text = "") {
|
|
9843
|
+
return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
|
|
9844
|
+
}
|
|
9825
9845
|
async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9826
9846
|
if (typeof client?.session?.messages !== "function") return null;
|
|
9827
|
-
const query = { limit };
|
|
9847
|
+
const query = { limit: clampOpenCodeMessageLimit(limit) };
|
|
9828
9848
|
if (directory) query.directory = directory;
|
|
9829
9849
|
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
9830
9850
|
}
|
|
9851
|
+
function openCodeResultSummary(result) {
|
|
9852
|
+
const data = result?.data ?? result;
|
|
9853
|
+
return {
|
|
9854
|
+
type: Array.isArray(data) ? "array" : typeof data,
|
|
9855
|
+
id: data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId || null,
|
|
9856
|
+
keys: data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).slice(0, 20) : [],
|
|
9857
|
+
dataKeys: result?.data && typeof result.data === "object" && !Array.isArray(result.data) ? Object.keys(result.data).slice(0, 20) : [],
|
|
9858
|
+
status: result?.status || result?.response?.status || null
|
|
9859
|
+
};
|
|
9860
|
+
}
|
|
9861
|
+
function normalizeOpenCodeMessageRole(message = {}) {
|
|
9862
|
+
return message.role || message.info?.role || message.author?.role || message.type || "";
|
|
9863
|
+
}
|
|
9864
|
+
function normalizeOpenCodeMessageAgent(message = {}) {
|
|
9865
|
+
return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
|
|
9866
|
+
}
|
|
9867
|
+
function normalizeOpenCodeMessageMode(message = {}) {
|
|
9868
|
+
return message.mode || message.info?.mode || message.metadata?.mode || "";
|
|
9869
|
+
}
|
|
9870
|
+
function normalizeOpenCodeMessageId(message = {}) {
|
|
9871
|
+
return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
|
|
9872
|
+
}
|
|
9873
|
+
function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
|
|
9874
|
+
const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
|
|
9875
|
+
const safeSnippetLength = Math.min(240, Math.max(20, Number(snippetLength) || 160));
|
|
9876
|
+
return list.map((message, index) => {
|
|
9877
|
+
const text = openCodeMessageText(message).replace(/\s+/g, " ").trim();
|
|
9878
|
+
return {
|
|
9879
|
+
index,
|
|
9880
|
+
id: normalizeOpenCodeMessageId(message),
|
|
9881
|
+
role: normalizeOpenCodeMessageRole(message),
|
|
9882
|
+
agent: normalizeOpenCodeMessageAgent(message),
|
|
9883
|
+
mode: normalizeOpenCodeMessageMode(message),
|
|
9884
|
+
text_length: text.length,
|
|
9885
|
+
text_hash: hashOpenCodeSessionText(text),
|
|
9886
|
+
snippet: text.length > safeSnippetLength ? `${text.slice(0, safeSnippetLength)}...` : text
|
|
9887
|
+
};
|
|
9888
|
+
});
|
|
9889
|
+
}
|
|
9890
|
+
function promptResultAssistantReturned(result) {
|
|
9891
|
+
const parts = normalizePromptResponseParts(result);
|
|
9892
|
+
const text = extractTextParts(parts);
|
|
9893
|
+
const data = result?.data ?? result;
|
|
9894
|
+
return Boolean(text || data?.role === "assistant" || data?.info?.role === "assistant");
|
|
9895
|
+
}
|
|
9896
|
+
async function createOpenCodeSessionControl(client, { directory, title, agent } = {}) {
|
|
9897
|
+
if (typeof client?.session?.create !== "function") throw new Error("OpenCode client does not expose session.create.");
|
|
9898
|
+
const body = { title };
|
|
9899
|
+
if (agent) body.agent = agent;
|
|
9900
|
+
const result = await client.session.create({ query: { directory }, body });
|
|
9901
|
+
const sessionId = extractOpenCodeSessionId(result);
|
|
9902
|
+
if (!sessionId) throw new Error("OpenCode session create response did not include a session id.");
|
|
9903
|
+
return {
|
|
9904
|
+
ok: true,
|
|
9905
|
+
session_id: sessionId,
|
|
9906
|
+
title,
|
|
9907
|
+
directory,
|
|
9908
|
+
agent: agent || null,
|
|
9909
|
+
result_summary: openCodeResultSummary(result)
|
|
9910
|
+
};
|
|
9911
|
+
}
|
|
9912
|
+
async function promptOpenCodeSessionControl(client, { sessionId, directory, text, agent, omitAgent = false, requireReadable = true } = {}) {
|
|
9913
|
+
if (typeof client?.session?.prompt !== "function") throw new Error("OpenCode client does not expose session.prompt.");
|
|
9914
|
+
if (requireReadable) await assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory });
|
|
9915
|
+
const safeText = clampOpenCodeSessionText(text);
|
|
9916
|
+
const body = { parts: [{ type: "text", text: safeText }] };
|
|
9917
|
+
if (!omitAgent && agent) body.agent = agent;
|
|
9918
|
+
const result = await client.session.prompt({ path: { id: sessionId }, query: { directory }, body });
|
|
9919
|
+
return {
|
|
9920
|
+
ok: true,
|
|
9921
|
+
session_id: sessionId,
|
|
9922
|
+
directory,
|
|
9923
|
+
agent: omitAgent ? null : agent || null,
|
|
9924
|
+
omit_agent: Boolean(omitAgent),
|
|
9925
|
+
text_length: safeText.length,
|
|
9926
|
+
text_truncated: String(text ?? "").length > safeText.length,
|
|
9927
|
+
text_hash: hashOpenCodeSessionText(safeText),
|
|
9928
|
+
assistant_returned: promptResultAssistantReturned(result),
|
|
9929
|
+
returned_parts_count: normalizePromptResponseParts(result).length,
|
|
9930
|
+
result_summary: openCodeResultSummary(result)
|
|
9931
|
+
};
|
|
9932
|
+
}
|
|
9933
|
+
async function assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory } = {}) {
|
|
9934
|
+
try {
|
|
9935
|
+
await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 1 });
|
|
9936
|
+
return true;
|
|
9937
|
+
} catch (error) {
|
|
9938
|
+
throw new Error(`OpenCode session '${sessionId}' is not readable for the requested safe directory.`);
|
|
9939
|
+
}
|
|
9940
|
+
}
|
|
9941
|
+
async function readOpenCodeSessionControl(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9942
|
+
const boundedLimit = clampOpenCodeMessageLimit(limit);
|
|
9943
|
+
const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: boundedLimit });
|
|
9944
|
+
if (!messages) throw new Error("OpenCode client does not expose session.messages.");
|
|
9945
|
+
return {
|
|
9946
|
+
ok: true,
|
|
9947
|
+
session_id: sessionId,
|
|
9948
|
+
directory: directory || null,
|
|
9949
|
+
limit: boundedLimit,
|
|
9950
|
+
count: messages.length,
|
|
9951
|
+
messages: summarizeOpenCodeMessages(messages)
|
|
9952
|
+
};
|
|
9953
|
+
}
|
|
9954
|
+
async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
|
|
9955
|
+
const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
|
|
9956
|
+
const marker = clampOpenCodeSessionText(requestedMarker);
|
|
9957
|
+
const create = await createOpenCodeSessionControl(client, {
|
|
9958
|
+
directory,
|
|
9959
|
+
title: `Optima session probe ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
9960
|
+
agent
|
|
9961
|
+
});
|
|
9962
|
+
const prompt = await promptOpenCodeSessionControl(client, {
|
|
9963
|
+
sessionId: create.session_id,
|
|
9964
|
+
directory,
|
|
9965
|
+
text: marker,
|
|
9966
|
+
agent,
|
|
9967
|
+
omitAgent: omitAgentOnPrompt,
|
|
9968
|
+
requireReadable: false
|
|
9969
|
+
});
|
|
9970
|
+
const rawMessages = await readOpenCodeSessionMessages(client, { sessionId: create.session_id, directory, limit: 50 });
|
|
9971
|
+
if (!rawMessages) throw new Error("OpenCode client does not expose session.messages.");
|
|
9972
|
+
const fullMessageText = rawMessages.map(openCodeMessageText).join("\n");
|
|
9973
|
+
const messages = {
|
|
9974
|
+
ok: true,
|
|
9975
|
+
session_id: create.session_id,
|
|
9976
|
+
directory,
|
|
9977
|
+
limit: 50,
|
|
9978
|
+
count: rawMessages.length,
|
|
9979
|
+
messages: summarizeOpenCodeMessages(rawMessages)
|
|
9980
|
+
};
|
|
9981
|
+
return {
|
|
9982
|
+
ok: true,
|
|
9983
|
+
session_id: create.session_id,
|
|
9984
|
+
directory,
|
|
9985
|
+
agent: agent || null,
|
|
9986
|
+
omit_agent_on_prompt: Boolean(omitAgentOnPrompt),
|
|
9987
|
+
marker_length: marker.length,
|
|
9988
|
+
marker_truncated: requestedMarker.length > marker.length,
|
|
9989
|
+
marker_hash: hashOpenCodeSessionText(marker),
|
|
9990
|
+
marker_visible: fullMessageText.includes(marker),
|
|
9991
|
+
assistant_visible: rawMessages.some((message) => normalizeLooseToken(normalizeOpenCodeMessageRole(message)) === "assistant" || Boolean(normalizeOpenCodeMessageAgent(message) && openCodeMessageText(message))),
|
|
9992
|
+
create,
|
|
9993
|
+
prompt,
|
|
9994
|
+
messages
|
|
9995
|
+
};
|
|
9996
|
+
}
|
|
9831
9997
|
function openCodeMessageText(message) {
|
|
9832
9998
|
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
9833
9999
|
const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
|
|
@@ -11471,7 +11637,22 @@ function isSameOrNestedPath(candidate, root) {
|
|
|
11471
11637
|
function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
|
|
11472
11638
|
if (options.clickUpWebhookActive === true) return true;
|
|
11473
11639
|
const validation = options.clickUpWebhookValidation;
|
|
11474
|
-
return validation?.complete === true && isSameOrNestedPath(worktree, validation.config?.basePath);
|
|
11640
|
+
return validation?.complete === true && validation?.ok !== false && isSameOrNestedPath(worktree, validation.config?.basePath);
|
|
11641
|
+
}
|
|
11642
|
+
function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
|
|
11643
|
+
const safe = safeWorktreeOrFailure(context, pluginWorktree);
|
|
11644
|
+
if (!safe.ok) return { ok: false, error: safe.message };
|
|
11645
|
+
const requested = String(requestedDirectory || "").trim() ? path2.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
|
|
11646
|
+
if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
|
|
11647
|
+
if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
|
|
11648
|
+
const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
|
|
11649
|
+
if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
|
|
11650
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path2.resolve(clickUpBasePath) };
|
|
11651
|
+
}
|
|
11652
|
+
return {
|
|
11653
|
+
ok: false,
|
|
11654
|
+
error: `Directory '${requested}' is outside the safe worktree '${safe.worktree}' and configured ClickUp base path.`
|
|
11655
|
+
};
|
|
11475
11656
|
}
|
|
11476
11657
|
function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, options = {}) {
|
|
11477
11658
|
const optimaActive = repoCfg && repoCfg.enabled === true;
|
|
@@ -11759,6 +11940,100 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
11759
11940
|
Restart or reload OpenCode manually if the newly scaffolded config or agents are not visible in this session. Optima did not dispose or reload the active OpenCode instance automatically to avoid aborting the current session.`;
|
|
11760
11941
|
}
|
|
11761
11942
|
}),
|
|
11943
|
+
optima_session_create: tool({
|
|
11944
|
+
description: "Create an OpenCode session through the installed structured SDK shape",
|
|
11945
|
+
args: {
|
|
11946
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
11947
|
+
title: tool.schema.string().describe("Session title"),
|
|
11948
|
+
agent: tool.schema.string().describe("Optional agent id for session creation")
|
|
11949
|
+
},
|
|
11950
|
+
async execute(args, context) {
|
|
11951
|
+
try {
|
|
11952
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
11953
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
11954
|
+
const result = await createOpenCodeSessionControl(input.client, {
|
|
11955
|
+
directory: directory.directory,
|
|
11956
|
+
title: args.title,
|
|
11957
|
+
agent: args.agent
|
|
11958
|
+
});
|
|
11959
|
+
return JSON.stringify(result, null, 2);
|
|
11960
|
+
} catch (error) {
|
|
11961
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
11962
|
+
}
|
|
11963
|
+
}
|
|
11964
|
+
}),
|
|
11965
|
+
optima_session_prompt: tool({
|
|
11966
|
+
description: "Prompt an existing OpenCode session through the installed structured SDK shape",
|
|
11967
|
+
args: {
|
|
11968
|
+
session_id: tool.schema.string().describe("OpenCode session id"),
|
|
11969
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
11970
|
+
text: tool.schema.string().describe("Text prompt to send"),
|
|
11971
|
+
agent: tool.schema.string().describe("Optional agent id for the prompt body"),
|
|
11972
|
+
omit_agent: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body")
|
|
11973
|
+
},
|
|
11974
|
+
async execute(args, context) {
|
|
11975
|
+
try {
|
|
11976
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
11977
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
11978
|
+
const result = await promptOpenCodeSessionControl(input.client, {
|
|
11979
|
+
sessionId: args.session_id,
|
|
11980
|
+
directory: directory.directory,
|
|
11981
|
+
text: args.text,
|
|
11982
|
+
agent: args.agent,
|
|
11983
|
+
omitAgent: String(args.omit_agent || "").toLowerCase() === "true"
|
|
11984
|
+
});
|
|
11985
|
+
return JSON.stringify(result, null, 2);
|
|
11986
|
+
} catch (error) {
|
|
11987
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
11988
|
+
}
|
|
11989
|
+
}
|
|
11990
|
+
}),
|
|
11991
|
+
optima_session_messages: tool({
|
|
11992
|
+
description: "Read and summarize OpenCode session messages through the installed structured SDK shape",
|
|
11993
|
+
args: {
|
|
11994
|
+
session_id: tool.schema.string().describe("OpenCode session id"),
|
|
11995
|
+
directory: tool.schema.string().describe("Optional project directory for the OpenCode session"),
|
|
11996
|
+
limit: tool.schema.number().describe("Optional message limit")
|
|
11997
|
+
},
|
|
11998
|
+
async execute(args, context) {
|
|
11999
|
+
try {
|
|
12000
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
12001
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
12002
|
+
const result = await readOpenCodeSessionControl(input.client, {
|
|
12003
|
+
sessionId: args.session_id,
|
|
12004
|
+
directory: directory.directory,
|
|
12005
|
+
limit: args.limit
|
|
12006
|
+
});
|
|
12007
|
+
return JSON.stringify(result, null, 2);
|
|
12008
|
+
} catch (error) {
|
|
12009
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
12010
|
+
}
|
|
12011
|
+
}
|
|
12012
|
+
}),
|
|
12013
|
+
optima_session_probe: tool({
|
|
12014
|
+
description: "Create, prompt, and read an OpenCode session without touching ClickUp state",
|
|
12015
|
+
args: {
|
|
12016
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
12017
|
+
agent: tool.schema.string().describe("Optional agent id to probe"),
|
|
12018
|
+
omit_agent_on_prompt: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body"),
|
|
12019
|
+
text: tool.schema.string().describe("Optional marker text to send")
|
|
12020
|
+
},
|
|
12021
|
+
async execute(args, context) {
|
|
12022
|
+
try {
|
|
12023
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
12024
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
12025
|
+
const result = await probeOpenCodeSessionControl(input.client, {
|
|
12026
|
+
directory: directory.directory,
|
|
12027
|
+
agent: args.agent,
|
|
12028
|
+
omitAgentOnPrompt: String(args.omit_agent_on_prompt || "").toLowerCase() === "true",
|
|
12029
|
+
text: args.text
|
|
12030
|
+
});
|
|
12031
|
+
return JSON.stringify(result, null, 2);
|
|
12032
|
+
} catch (error) {
|
|
12033
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
12034
|
+
}
|
|
12035
|
+
}
|
|
12036
|
+
}),
|
|
11762
12037
|
optima_clickup_sync_summary: tool({
|
|
11763
12038
|
description: "Generate a dry-run ClickUp summary/comment payload from Optima Markdown task and evidence artifacts",
|
|
11764
12039
|
args: {
|
|
@@ -12227,7 +12502,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
12227
12502
|
}
|
|
12228
12503
|
};
|
|
12229
12504
|
}
|
|
12230
|
-
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, createOpenCodeSession, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, 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 };
|
|
12505
|
+
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, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, 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 };
|
|
12231
12506
|
export {
|
|
12232
12507
|
OptimaPlugin as default
|
|
12233
12508
|
};
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -9263,17 +9263,20 @@ function clickUpWebhookLocationCompatible(webhook = {}, config = {}) {
|
|
|
9263
9263
|
}
|
|
9264
9264
|
return true;
|
|
9265
9265
|
}
|
|
9266
|
-
async function findReusableClickUpWebhook(config, clickupClient = null) {
|
|
9266
|
+
async function findReusableClickUpWebhook(config, clickupClient = null, existingState = null) {
|
|
9267
9267
|
if (!clickupClient?.listWebhooks) return null;
|
|
9268
9268
|
const listed = await clickupClient.listWebhooks({ teamId: config.teamId });
|
|
9269
|
+
let secretlessMatch = null;
|
|
9269
9270
|
for (const webhook of clickUpWebhookListItems(listed)) {
|
|
9270
9271
|
const remote = normalizeClickUpWebhookApiResponse(webhook, config);
|
|
9271
9272
|
if (remote.publicUrl !== config.webhook.publicUrl) continue;
|
|
9272
9273
|
if (!clickUpWebhookLocationCompatible(webhook, config)) continue;
|
|
9273
|
-
|
|
9274
|
-
|
|
9274
|
+
const existingSecret = existingState?.webhookId === remote.webhookId ? existingState.secret : "";
|
|
9275
|
+
const reusable = remote.secret ? remote : { ...remote, secret: existingSecret };
|
|
9276
|
+
if (isClickUpWebhookStateActive(reusable, config)) return reusable;
|
|
9277
|
+
if (remote.webhookId && !secretlessMatch) secretlessMatch = { ...remote, active: false, reason: "remote_secret_unavailable" };
|
|
9275
9278
|
}
|
|
9276
|
-
return
|
|
9279
|
+
return secretlessMatch;
|
|
9277
9280
|
}
|
|
9278
9281
|
async function validateClickUpWebhookState(state, config, clickupClient = null, { allowRemoteUnhealthyLocalRecovery = false } = {}) {
|
|
9279
9282
|
if (!isClickUpWebhookStateActive(state, config)) return { valid: false, reason: "state_incomplete" };
|
|
@@ -9318,11 +9321,16 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
|
|
|
9318
9321
|
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: existingValidation.mode });
|
|
9319
9322
|
return { active: true, valid: true, mode: existingValidation.mode, limitation: existingValidation.limitation, state };
|
|
9320
9323
|
}
|
|
9321
|
-
const reusableRemote = await findReusableClickUpWebhook(config, clickupClient);
|
|
9324
|
+
const reusableRemote = await findReusableClickUpWebhook(config, clickupClient, existing);
|
|
9322
9325
|
if (reusableRemote) {
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
+
if (isClickUpWebhookStateActive(reusableRemote, config)) {
|
|
9327
|
+
const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
|
|
9328
|
+
const mode2 = reusableRemote.secret === existing.secret && existing.webhookId === reusableRemote.webhookId ? "remote_discovered_local_secret" : "remote_discovered";
|
|
9329
|
+
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: mode2 });
|
|
9330
|
+
return { active: true, valid: true, mode: mode2, state };
|
|
9331
|
+
}
|
|
9332
|
+
clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_preserved", webhookId: reusableRemote.webhookId, reason: reusableRemote.reason || "remote_webhook_exists_without_secret" });
|
|
9333
|
+
return { active: false, valid: false, reason: reusableRemote.reason || "remote_webhook_exists_without_secret", state: existing, remote: reusableRemote };
|
|
9326
9334
|
}
|
|
9327
9335
|
if (existing.webhookId && clickupClient?.deleteWebhook) {
|
|
9328
9336
|
await deleteClickUpWebhookBestEffort({ webhookId: existing.webhookId, clickupClient, worktree, reason: existingValidation.reason || "startup_self_heal" });
|
|
@@ -9829,12 +9837,170 @@ function normalizeOpenCodeSessionMessages(result) {
|
|
|
9829
9837
|
if (Array.isArray(data?.items)) return [...data.items];
|
|
9830
9838
|
return [];
|
|
9831
9839
|
}
|
|
9840
|
+
function clampOpenCodeMessageLimit(limit) {
|
|
9841
|
+
const value = Number(limit);
|
|
9842
|
+
if (!Number.isFinite(value)) return 20;
|
|
9843
|
+
return Math.min(50, Math.max(1, Math.floor(value)));
|
|
9844
|
+
}
|
|
9845
|
+
function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
|
|
9846
|
+
const value = String(text ?? "");
|
|
9847
|
+
return value.length > maxLength ? value.slice(0, maxLength) : value;
|
|
9848
|
+
}
|
|
9849
|
+
function hashOpenCodeSessionText(text = "") {
|
|
9850
|
+
return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
|
|
9851
|
+
}
|
|
9832
9852
|
async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9833
9853
|
if (typeof client?.session?.messages !== "function") return null;
|
|
9834
|
-
const query = { limit };
|
|
9854
|
+
const query = { limit: clampOpenCodeMessageLimit(limit) };
|
|
9835
9855
|
if (directory) query.directory = directory;
|
|
9836
9856
|
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
9837
9857
|
}
|
|
9858
|
+
function openCodeResultSummary(result) {
|
|
9859
|
+
const data = result?.data ?? result;
|
|
9860
|
+
return {
|
|
9861
|
+
type: Array.isArray(data) ? "array" : typeof data,
|
|
9862
|
+
id: data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId || null,
|
|
9863
|
+
keys: data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).slice(0, 20) : [],
|
|
9864
|
+
dataKeys: result?.data && typeof result.data === "object" && !Array.isArray(result.data) ? Object.keys(result.data).slice(0, 20) : [],
|
|
9865
|
+
status: result?.status || result?.response?.status || null
|
|
9866
|
+
};
|
|
9867
|
+
}
|
|
9868
|
+
function normalizeOpenCodeMessageRole(message = {}) {
|
|
9869
|
+
return message.role || message.info?.role || message.author?.role || message.type || "";
|
|
9870
|
+
}
|
|
9871
|
+
function normalizeOpenCodeMessageAgent(message = {}) {
|
|
9872
|
+
return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
|
|
9873
|
+
}
|
|
9874
|
+
function normalizeOpenCodeMessageMode(message = {}) {
|
|
9875
|
+
return message.mode || message.info?.mode || message.metadata?.mode || "";
|
|
9876
|
+
}
|
|
9877
|
+
function normalizeOpenCodeMessageId(message = {}) {
|
|
9878
|
+
return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
|
|
9879
|
+
}
|
|
9880
|
+
function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
|
|
9881
|
+
const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
|
|
9882
|
+
const safeSnippetLength = Math.min(240, Math.max(20, Number(snippetLength) || 160));
|
|
9883
|
+
return list.map((message, index) => {
|
|
9884
|
+
const text = openCodeMessageText(message).replace(/\s+/g, " ").trim();
|
|
9885
|
+
return {
|
|
9886
|
+
index,
|
|
9887
|
+
id: normalizeOpenCodeMessageId(message),
|
|
9888
|
+
role: normalizeOpenCodeMessageRole(message),
|
|
9889
|
+
agent: normalizeOpenCodeMessageAgent(message),
|
|
9890
|
+
mode: normalizeOpenCodeMessageMode(message),
|
|
9891
|
+
text_length: text.length,
|
|
9892
|
+
text_hash: hashOpenCodeSessionText(text),
|
|
9893
|
+
snippet: text.length > safeSnippetLength ? `${text.slice(0, safeSnippetLength)}...` : text
|
|
9894
|
+
};
|
|
9895
|
+
});
|
|
9896
|
+
}
|
|
9897
|
+
function promptResultAssistantReturned(result) {
|
|
9898
|
+
const parts = normalizePromptResponseParts(result);
|
|
9899
|
+
const text = extractTextParts(parts);
|
|
9900
|
+
const data = result?.data ?? result;
|
|
9901
|
+
return Boolean(text || data?.role === "assistant" || data?.info?.role === "assistant");
|
|
9902
|
+
}
|
|
9903
|
+
async function createOpenCodeSessionControl(client, { directory, title, agent } = {}) {
|
|
9904
|
+
if (typeof client?.session?.create !== "function") throw new Error("OpenCode client does not expose session.create.");
|
|
9905
|
+
const body = { title };
|
|
9906
|
+
if (agent) body.agent = agent;
|
|
9907
|
+
const result = await client.session.create({ query: { directory }, body });
|
|
9908
|
+
const sessionId = extractOpenCodeSessionId(result);
|
|
9909
|
+
if (!sessionId) throw new Error("OpenCode session create response did not include a session id.");
|
|
9910
|
+
return {
|
|
9911
|
+
ok: true,
|
|
9912
|
+
session_id: sessionId,
|
|
9913
|
+
title,
|
|
9914
|
+
directory,
|
|
9915
|
+
agent: agent || null,
|
|
9916
|
+
result_summary: openCodeResultSummary(result)
|
|
9917
|
+
};
|
|
9918
|
+
}
|
|
9919
|
+
async function promptOpenCodeSessionControl(client, { sessionId, directory, text, agent, omitAgent = false, requireReadable = true } = {}) {
|
|
9920
|
+
if (typeof client?.session?.prompt !== "function") throw new Error("OpenCode client does not expose session.prompt.");
|
|
9921
|
+
if (requireReadable) await assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory });
|
|
9922
|
+
const safeText = clampOpenCodeSessionText(text);
|
|
9923
|
+
const body = { parts: [{ type: "text", text: safeText }] };
|
|
9924
|
+
if (!omitAgent && agent) body.agent = agent;
|
|
9925
|
+
const result = await client.session.prompt({ path: { id: sessionId }, query: { directory }, body });
|
|
9926
|
+
return {
|
|
9927
|
+
ok: true,
|
|
9928
|
+
session_id: sessionId,
|
|
9929
|
+
directory,
|
|
9930
|
+
agent: omitAgent ? null : agent || null,
|
|
9931
|
+
omit_agent: Boolean(omitAgent),
|
|
9932
|
+
text_length: safeText.length,
|
|
9933
|
+
text_truncated: String(text ?? "").length > safeText.length,
|
|
9934
|
+
text_hash: hashOpenCodeSessionText(safeText),
|
|
9935
|
+
assistant_returned: promptResultAssistantReturned(result),
|
|
9936
|
+
returned_parts_count: normalizePromptResponseParts(result).length,
|
|
9937
|
+
result_summary: openCodeResultSummary(result)
|
|
9938
|
+
};
|
|
9939
|
+
}
|
|
9940
|
+
async function assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory } = {}) {
|
|
9941
|
+
try {
|
|
9942
|
+
await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 1 });
|
|
9943
|
+
return true;
|
|
9944
|
+
} catch (error) {
|
|
9945
|
+
throw new Error(`OpenCode session '${sessionId}' is not readable for the requested safe directory.`);
|
|
9946
|
+
}
|
|
9947
|
+
}
|
|
9948
|
+
async function readOpenCodeSessionControl(client, { sessionId, directory, limit = 20 } = {}) {
|
|
9949
|
+
const boundedLimit = clampOpenCodeMessageLimit(limit);
|
|
9950
|
+
const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: boundedLimit });
|
|
9951
|
+
if (!messages) throw new Error("OpenCode client does not expose session.messages.");
|
|
9952
|
+
return {
|
|
9953
|
+
ok: true,
|
|
9954
|
+
session_id: sessionId,
|
|
9955
|
+
directory: directory || null,
|
|
9956
|
+
limit: boundedLimit,
|
|
9957
|
+
count: messages.length,
|
|
9958
|
+
messages: summarizeOpenCodeMessages(messages)
|
|
9959
|
+
};
|
|
9960
|
+
}
|
|
9961
|
+
async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
|
|
9962
|
+
const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
|
|
9963
|
+
const marker = clampOpenCodeSessionText(requestedMarker);
|
|
9964
|
+
const create = await createOpenCodeSessionControl(client, {
|
|
9965
|
+
directory,
|
|
9966
|
+
title: `Optima session probe ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
9967
|
+
agent
|
|
9968
|
+
});
|
|
9969
|
+
const prompt = await promptOpenCodeSessionControl(client, {
|
|
9970
|
+
sessionId: create.session_id,
|
|
9971
|
+
directory,
|
|
9972
|
+
text: marker,
|
|
9973
|
+
agent,
|
|
9974
|
+
omitAgent: omitAgentOnPrompt,
|
|
9975
|
+
requireReadable: false
|
|
9976
|
+
});
|
|
9977
|
+
const rawMessages = await readOpenCodeSessionMessages(client, { sessionId: create.session_id, directory, limit: 50 });
|
|
9978
|
+
if (!rawMessages) throw new Error("OpenCode client does not expose session.messages.");
|
|
9979
|
+
const fullMessageText = rawMessages.map(openCodeMessageText).join("\n");
|
|
9980
|
+
const messages = {
|
|
9981
|
+
ok: true,
|
|
9982
|
+
session_id: create.session_id,
|
|
9983
|
+
directory,
|
|
9984
|
+
limit: 50,
|
|
9985
|
+
count: rawMessages.length,
|
|
9986
|
+
messages: summarizeOpenCodeMessages(rawMessages)
|
|
9987
|
+
};
|
|
9988
|
+
return {
|
|
9989
|
+
ok: true,
|
|
9990
|
+
session_id: create.session_id,
|
|
9991
|
+
directory,
|
|
9992
|
+
agent: agent || null,
|
|
9993
|
+
omit_agent_on_prompt: Boolean(omitAgentOnPrompt),
|
|
9994
|
+
marker_length: marker.length,
|
|
9995
|
+
marker_truncated: requestedMarker.length > marker.length,
|
|
9996
|
+
marker_hash: hashOpenCodeSessionText(marker),
|
|
9997
|
+
marker_visible: fullMessageText.includes(marker),
|
|
9998
|
+
assistant_visible: rawMessages.some((message) => normalizeLooseToken(normalizeOpenCodeMessageRole(message)) === "assistant" || Boolean(normalizeOpenCodeMessageAgent(message) && openCodeMessageText(message))),
|
|
9999
|
+
create,
|
|
10000
|
+
prompt,
|
|
10001
|
+
messages
|
|
10002
|
+
};
|
|
10003
|
+
}
|
|
9838
10004
|
function openCodeMessageText(message) {
|
|
9839
10005
|
const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
|
|
9840
10006
|
const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
|
|
@@ -11478,7 +11644,22 @@ function isSameOrNestedPath(candidate, root) {
|
|
|
11478
11644
|
function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
|
|
11479
11645
|
if (options.clickUpWebhookActive === true) return true;
|
|
11480
11646
|
const validation = options.clickUpWebhookValidation;
|
|
11481
|
-
return validation?.complete === true && isSameOrNestedPath(worktree, validation.config?.basePath);
|
|
11647
|
+
return validation?.complete === true && validation?.ok !== false && isSameOrNestedPath(worktree, validation.config?.basePath);
|
|
11648
|
+
}
|
|
11649
|
+
function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
|
|
11650
|
+
const safe = safeWorktreeOrFailure(context, pluginWorktree);
|
|
11651
|
+
if (!safe.ok) return { ok: false, error: safe.message };
|
|
11652
|
+
const requested = String(requestedDirectory || "").trim() ? path2.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
|
|
11653
|
+
if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
|
|
11654
|
+
if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
|
|
11655
|
+
const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
|
|
11656
|
+
if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
|
|
11657
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path2.resolve(clickUpBasePath) };
|
|
11658
|
+
}
|
|
11659
|
+
return {
|
|
11660
|
+
ok: false,
|
|
11661
|
+
error: `Directory '${requested}' is outside the safe worktree '${safe.worktree}' and configured ClickUp base path.`
|
|
11662
|
+
};
|
|
11482
11663
|
}
|
|
11483
11664
|
function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, options = {}) {
|
|
11484
11665
|
const optimaActive = repoCfg && repoCfg.enabled === true;
|
|
@@ -11766,6 +11947,100 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
11766
11947
|
Restart or reload OpenCode manually if the newly scaffolded config or agents are not visible in this session. Optima did not dispose or reload the active OpenCode instance automatically to avoid aborting the current session.`;
|
|
11767
11948
|
}
|
|
11768
11949
|
}),
|
|
11950
|
+
optima_session_create: tool({
|
|
11951
|
+
description: "Create an OpenCode session through the installed structured SDK shape",
|
|
11952
|
+
args: {
|
|
11953
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
11954
|
+
title: tool.schema.string().describe("Session title"),
|
|
11955
|
+
agent: tool.schema.string().describe("Optional agent id for session creation")
|
|
11956
|
+
},
|
|
11957
|
+
async execute(args, context) {
|
|
11958
|
+
try {
|
|
11959
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
11960
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
11961
|
+
const result = await createOpenCodeSessionControl(input.client, {
|
|
11962
|
+
directory: directory.directory,
|
|
11963
|
+
title: args.title,
|
|
11964
|
+
agent: args.agent
|
|
11965
|
+
});
|
|
11966
|
+
return JSON.stringify(result, null, 2);
|
|
11967
|
+
} catch (error) {
|
|
11968
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
11969
|
+
}
|
|
11970
|
+
}
|
|
11971
|
+
}),
|
|
11972
|
+
optima_session_prompt: tool({
|
|
11973
|
+
description: "Prompt an existing OpenCode session through the installed structured SDK shape",
|
|
11974
|
+
args: {
|
|
11975
|
+
session_id: tool.schema.string().describe("OpenCode session id"),
|
|
11976
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
11977
|
+
text: tool.schema.string().describe("Text prompt to send"),
|
|
11978
|
+
agent: tool.schema.string().describe("Optional agent id for the prompt body"),
|
|
11979
|
+
omit_agent: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body")
|
|
11980
|
+
},
|
|
11981
|
+
async execute(args, context) {
|
|
11982
|
+
try {
|
|
11983
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
11984
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
11985
|
+
const result = await promptOpenCodeSessionControl(input.client, {
|
|
11986
|
+
sessionId: args.session_id,
|
|
11987
|
+
directory: directory.directory,
|
|
11988
|
+
text: args.text,
|
|
11989
|
+
agent: args.agent,
|
|
11990
|
+
omitAgent: String(args.omit_agent || "").toLowerCase() === "true"
|
|
11991
|
+
});
|
|
11992
|
+
return JSON.stringify(result, null, 2);
|
|
11993
|
+
} catch (error) {
|
|
11994
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
11995
|
+
}
|
|
11996
|
+
}
|
|
11997
|
+
}),
|
|
11998
|
+
optima_session_messages: tool({
|
|
11999
|
+
description: "Read and summarize OpenCode session messages through the installed structured SDK shape",
|
|
12000
|
+
args: {
|
|
12001
|
+
session_id: tool.schema.string().describe("OpenCode session id"),
|
|
12002
|
+
directory: tool.schema.string().describe("Optional project directory for the OpenCode session"),
|
|
12003
|
+
limit: tool.schema.number().describe("Optional message limit")
|
|
12004
|
+
},
|
|
12005
|
+
async execute(args, context) {
|
|
12006
|
+
try {
|
|
12007
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
12008
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
12009
|
+
const result = await readOpenCodeSessionControl(input.client, {
|
|
12010
|
+
sessionId: args.session_id,
|
|
12011
|
+
directory: directory.directory,
|
|
12012
|
+
limit: args.limit
|
|
12013
|
+
});
|
|
12014
|
+
return JSON.stringify(result, null, 2);
|
|
12015
|
+
} catch (error) {
|
|
12016
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
}),
|
|
12020
|
+
optima_session_probe: tool({
|
|
12021
|
+
description: "Create, prompt, and read an OpenCode session without touching ClickUp state",
|
|
12022
|
+
args: {
|
|
12023
|
+
directory: tool.schema.string().describe("Project directory for the OpenCode session"),
|
|
12024
|
+
agent: tool.schema.string().describe("Optional agent id to probe"),
|
|
12025
|
+
omit_agent_on_prompt: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body"),
|
|
12026
|
+
text: tool.schema.string().describe("Optional marker text to send")
|
|
12027
|
+
},
|
|
12028
|
+
async execute(args, context) {
|
|
12029
|
+
try {
|
|
12030
|
+
const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
|
|
12031
|
+
if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
|
|
12032
|
+
const result = await probeOpenCodeSessionControl(input.client, {
|
|
12033
|
+
directory: directory.directory,
|
|
12034
|
+
agent: args.agent,
|
|
12035
|
+
omitAgentOnPrompt: String(args.omit_agent_on_prompt || "").toLowerCase() === "true",
|
|
12036
|
+
text: args.text
|
|
12037
|
+
});
|
|
12038
|
+
return JSON.stringify(result, null, 2);
|
|
12039
|
+
} catch (error) {
|
|
12040
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
12041
|
+
}
|
|
12042
|
+
}
|
|
12043
|
+
}),
|
|
11769
12044
|
optima_clickup_sync_summary: tool({
|
|
11770
12045
|
description: "Generate a dry-run ClickUp summary/comment payload from Optima Markdown task and evidence artifacts",
|
|
11771
12046
|
args: {
|
|
@@ -12234,7 +12509,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
12234
12509
|
}
|
|
12235
12510
|
};
|
|
12236
12511
|
}
|
|
12237
|
-
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, createOpenCodeSession, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, 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 };
|
|
12512
|
+
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, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, 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 };
|
|
12238
12513
|
|
|
12239
12514
|
// src/sanitize_cli.js
|
|
12240
12515
|
var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
|