UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

132 lines (131 loc) 4 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import "./string-coerce-runtime-GQa0ehRA.js"; //#region extensions/anthropic/cli-user-input.ts function createClaudeCliUserInputAuthorizer(context) { const requests = /* @__PURE__ */ new Map(); return { authorize(params) { const existing = params.toolUseId ? requests.get(params.toolUseId) : void 0; if (existing) return existing; const request = runClaudeUserInput(context, params); if (params.toolUseId) requests.set(params.toolUseId, request); return request; } }; } async function runClaudeUserInput(context, params) { const parsed = readClaudeUserInputQuestions(params.input); if (!parsed.ok) return { behavior: "deny", message: `OpenClaw rejected malformed Claude user questions: ${parsed.failure}. Correct the invalid field and retry AskUserQuestion.` }; const questions = parsed.questions; const result = await context.requestUserInput({ toolName: "AskUserQuestion", questions, intro: "Claude needs input:", ...params.toolUseId ? { toolCallId: params.toolUseId } : {}, abortSignal: params.signal }); if (result.status !== "answered") return { behavior: "deny", message: `${result.message} Continue with your best judgment.` }; const answers = {}; questions.forEach((question) => { answers[question.question] = (result.answers[question.id] ?? []).join(", "); }); return { behavior: "allow", updatedInput: { ...params.input, answers } }; } function readClaudeUserInputQuestions(input) { const rawQuestions = input.questions; if (!Array.isArray(rawQuestions) || rawQuestions.length < 1 || rawQuestions.length > 4) return { ok: false, failure: "questions must be an array of 1 to 4 questions" }; const questions = []; for (const [index, rawQuestion] of rawQuestions.entries()) { const questionPath = `questions[${index}]`; if (!isRecord(rawQuestion)) return { ok: false, failure: `${questionPath} must be an object` }; const question = readBoundedText(rawQuestion.question, 4096); if (!question.ok) return { ok: false, failure: `${questionPath}.question ${question.failure}` }; const header = readBoundedText(rawQuestion.header, 12); if (!header.ok) return { ok: false, failure: `${questionPath}.header ${header.failure}` }; const rawOptions = rawQuestion.options; if (!Array.isArray(rawOptions) || rawOptions.length < 2 || rawOptions.length > 4) return { ok: false, failure: `${questionPath}.options must be an array of 2 to 4 options` }; if (typeof rawQuestion.multiSelect !== "boolean") return { ok: false, failure: `${questionPath}.multiSelect must be a boolean` }; const options = []; for (const [optionIndex, rawOption] of rawOptions.entries()) { const optionPath = `${questionPath}.options[${optionIndex}]`; if (!isRecord(rawOption)) return { ok: false, failure: `${optionPath} must be an object` }; const label = readBoundedText(rawOption.label, 256); if (!label.ok) return { ok: false, failure: `${optionPath}.label ${label.failure}` }; const description = readBoundedText(rawOption.description, 1024); if (!description.ok) return { ok: false, failure: `${optionPath}.description ${description.failure}` }; options.push({ label: label.text, description: description.text }); } questions.push({ id: `question_${index + 1}`, header: header.text, question: question.text, multiSelect: rawQuestion.multiSelect, isOther: true, options }); } return { ok: true, questions }; } function readBoundedText(value, maxLength) { if (typeof value !== "string") return { ok: false, failure: "must be a string" }; if (value.length === 0) return { ok: false, failure: "must not be empty" }; if (value.length > maxLength) return { ok: false, failure: `must be at most ${maxLength} characters` }; return { ok: true, text: value }; } //#endregion export { createClaudeCliUserInputAuthorizer as t };