feat(core): merge backup core changes with post-split functionality
This commit is contained in:
@@ -18,7 +18,6 @@ Core fields:
|
||||
- effort (string, optional): reasoning effort passed via --effort (low|medium|high)
|
||||
- chrome (boolean, optional): pass --chrome when running Claude
|
||||
- promptTemplate (string, optional): run prompt template
|
||||
- bootstrapPromptTemplate (string, optional): first-run prompt template
|
||||
- maxTurnsPerRun (number, optional): max turns for one run
|
||||
- dangerouslySkipPermissions (boolean, optional): pass --dangerously-skip-permissions to claude
|
||||
- command (string, optional): defaults to "claude"
|
||||
|
||||
@@ -261,7 +261,6 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
config.promptTemplate,
|
||||
"You are agent {{agent.id}} ({{agent.name}}). Continue your Paperclip work.",
|
||||
);
|
||||
const bootstrapTemplate = asString(config.bootstrapPromptTemplate, promptTemplate);
|
||||
const model = asString(config.model, "");
|
||||
const effort = asString(config.effort, "");
|
||||
const chrome = asBoolean(config.chrome, false);
|
||||
@@ -269,6 +268,11 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, false);
|
||||
const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||
const instructionsFileDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : "";
|
||||
const commandNotes = instructionsFilePath
|
||||
? [
|
||||
`Injected agent instructions via --append-system-prompt-file ${instructionsFilePath} (with path directive appended)`,
|
||||
]
|
||||
: [];
|
||||
|
||||
const runtimeConfig = await buildClaudeRuntimeConfig({
|
||||
runId,
|
||||
@@ -316,8 +320,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
`[paperclip] Claude session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`,
|
||||
);
|
||||
}
|
||||
const template = sessionId ? promptTemplate : bootstrapTemplate;
|
||||
const prompt = renderTemplate(template, {
|
||||
const prompt = renderTemplate(promptTemplate, {
|
||||
agentId: agent.id,
|
||||
companyId: agent.companyId,
|
||||
runId,
|
||||
@@ -367,6 +370,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
command,
|
||||
cwd,
|
||||
commandArgs: args,
|
||||
commandNotes,
|
||||
env: redactEnvForLogs(env),
|
||||
prompt,
|
||||
context,
|
||||
|
||||
@@ -55,7 +55,6 @@ export function buildClaudeLocalConfig(v: CreateConfigValues): Record<string, un
|
||||
if (v.cwd) ac.cwd = v.cwd;
|
||||
if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath;
|
||||
if (v.promptTemplate) ac.promptTemplate = v.promptTemplate;
|
||||
if (v.bootstrapPrompt) ac.bootstrapPromptTemplate = v.bootstrapPrompt;
|
||||
if (v.model) ac.model = v.model;
|
||||
if (v.thinkingEffort) ac.effort = v.thinkingEffort;
|
||||
if (v.chrome) ac.chrome = true;
|
||||
|
||||
@@ -23,7 +23,6 @@ Core fields:
|
||||
- model (string, optional): Codex model id
|
||||
- modelReasoningEffort (string, optional): reasoning effort override (minimal|low|medium|high) passed via -c model_reasoning_effort=...
|
||||
- promptTemplate (string, optional): run prompt template
|
||||
- bootstrapPromptTemplate (string, optional): first-run prompt template
|
||||
- search (boolean, optional): run codex with --search
|
||||
- dangerouslyBypassApprovalsAndSandbox (boolean, optional): run with bypass flag
|
||||
- command (string, optional): defaults to "codex"
|
||||
|
||||
@@ -105,7 +105,6 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
config.promptTemplate,
|
||||
"You are agent {{agent.id}} ({{agent.name}}). Continue your Paperclip work.",
|
||||
);
|
||||
const bootstrapTemplate = asString(config.bootstrapPromptTemplate, promptTemplate);
|
||||
const command = asString(config.command, "codex");
|
||||
const model = asString(config.model, "");
|
||||
const modelReasoningEffort = asString(
|
||||
@@ -231,11 +230,11 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
);
|
||||
}
|
||||
const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||
const instructionsDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : "";
|
||||
let instructionsPrefix = "";
|
||||
if (instructionsFilePath) {
|
||||
try {
|
||||
const instructionsContents = await fs.readFile(instructionsFilePath, "utf8");
|
||||
const instructionsDir = `${path.dirname(instructionsFilePath)}/`;
|
||||
instructionsPrefix =
|
||||
`${instructionsContents}\n\n` +
|
||||
`The above agent instructions were loaded from ${instructionsFilePath}. ` +
|
||||
@@ -252,8 +251,19 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
);
|
||||
}
|
||||
}
|
||||
const template = sessionId ? promptTemplate : bootstrapTemplate;
|
||||
const renderedPrompt = renderTemplate(template, {
|
||||
const commandNotes = (() => {
|
||||
if (!instructionsFilePath) return [] as string[];
|
||||
if (instructionsPrefix.length > 0) {
|
||||
return [
|
||||
`Loaded agent instructions from ${instructionsFilePath}`,
|
||||
`Prepended instructions + path directive to stdin prompt (relative references from ${instructionsDir}).`,
|
||||
];
|
||||
}
|
||||
return [
|
||||
`Configured instructionsFilePath ${instructionsFilePath}, but file could not be read; continuing without injected instructions.`,
|
||||
];
|
||||
})();
|
||||
const renderedPrompt = renderTemplate(promptTemplate, {
|
||||
agentId: agent.id,
|
||||
companyId: agent.companyId,
|
||||
runId,
|
||||
@@ -283,6 +293,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
||||
adapterType: "codex_local",
|
||||
command,
|
||||
cwd,
|
||||
commandNotes,
|
||||
commandArgs: args.map((value, idx) => {
|
||||
if (idx === args.length - 1 && value !== "-") return `<prompt ${prompt.length} chars>`;
|
||||
return value;
|
||||
|
||||
@@ -55,7 +55,6 @@ export function buildCodexLocalConfig(v: CreateConfigValues): Record<string, unk
|
||||
if (v.cwd) ac.cwd = v.cwd;
|
||||
if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath;
|
||||
if (v.promptTemplate) ac.promptTemplate = v.promptTemplate;
|
||||
if (v.bootstrapPrompt) ac.bootstrapPromptTemplate = v.bootstrapPrompt;
|
||||
if (v.model) ac.model = v.model;
|
||||
if (v.thinkingEffort) ac.modelReasoningEffort = v.thinkingEffort;
|
||||
ac.timeoutSec = 0;
|
||||
|
||||
@@ -16,6 +16,81 @@ function isLoopbackHost(hostname: string): boolean {
|
||||
return value === "localhost" || value === "127.0.0.1" || value === "::1";
|
||||
}
|
||||
|
||||
function normalizeHostname(value: string | null | undefined): string | null {
|
||||
if (!value) return null;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return null;
|
||||
if (trimmed.startsWith("[")) {
|
||||
const end = trimmed.indexOf("]");
|
||||
return end > 1 ? trimmed.slice(1, end).toLowerCase() : trimmed.toLowerCase();
|
||||
}
|
||||
const firstColon = trimmed.indexOf(":");
|
||||
if (firstColon > -1) return trimmed.slice(0, firstColon).toLowerCase();
|
||||
return trimmed.toLowerCase();
|
||||
}
|
||||
|
||||
function pushDeploymentDiagnostics(
|
||||
checks: AdapterEnvironmentCheck[],
|
||||
ctx: AdapterEnvironmentTestContext,
|
||||
endpointUrl: URL | null,
|
||||
) {
|
||||
const mode = ctx.deployment?.mode;
|
||||
const exposure = ctx.deployment?.exposure;
|
||||
const bindHost = normalizeHostname(ctx.deployment?.bindHost ?? null);
|
||||
const allowSet = new Set(
|
||||
(ctx.deployment?.allowedHostnames ?? [])
|
||||
.map((entry) => normalizeHostname(entry))
|
||||
.filter((entry): entry is string => Boolean(entry)),
|
||||
);
|
||||
const endpointHost = endpointUrl ? normalizeHostname(endpointUrl.hostname) : null;
|
||||
|
||||
if (!mode) return;
|
||||
|
||||
checks.push({
|
||||
code: "openclaw_deployment_context",
|
||||
level: "info",
|
||||
message: `Deployment context: mode=${mode}${exposure ? ` exposure=${exposure}` : ""}`,
|
||||
});
|
||||
|
||||
if (mode === "authenticated" && exposure === "private") {
|
||||
if (bindHost && !isLoopbackHost(bindHost) && !allowSet.has(bindHost)) {
|
||||
checks.push({
|
||||
code: "openclaw_private_bind_hostname_not_allowed",
|
||||
level: "warn",
|
||||
message: `Paperclip bind host "${bindHost}" is not in allowed hostnames.`,
|
||||
hint: `Run pnpm paperclip allowed-hostname ${bindHost} so remote OpenClaw callbacks can pass host checks.`,
|
||||
});
|
||||
}
|
||||
|
||||
if (!bindHost || isLoopbackHost(bindHost)) {
|
||||
checks.push({
|
||||
code: "openclaw_private_bind_loopback",
|
||||
level: "warn",
|
||||
message: "Paperclip is bound to loopback in authenticated/private mode.",
|
||||
hint: "Bind to a reachable private hostname/IP so remote OpenClaw agents can call back.",
|
||||
});
|
||||
}
|
||||
|
||||
if (endpointHost && !isLoopbackHost(endpointHost) && allowSet.size === 0) {
|
||||
checks.push({
|
||||
code: "openclaw_private_no_allowed_hostnames",
|
||||
level: "warn",
|
||||
message: "No explicit allowed hostnames are configured for authenticated/private mode.",
|
||||
hint: "Set one with pnpm paperclip allowed-hostname <host> when OpenClaw runs on another machine.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (mode === "authenticated" && exposure === "public" && endpointUrl && endpointUrl.protocol !== "https:") {
|
||||
checks.push({
|
||||
code: "openclaw_public_http_endpoint",
|
||||
level: "warn",
|
||||
message: "OpenClaw endpoint uses HTTP in authenticated/public mode.",
|
||||
hint: "Prefer HTTPS for public deployments.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function testEnvironment(
|
||||
ctx: AdapterEnvironmentTestContext,
|
||||
): Promise<AdapterEnvironmentTestResult> {
|
||||
@@ -75,6 +150,8 @@ export async function testEnvironment(
|
||||
}
|
||||
}
|
||||
|
||||
pushDeploymentDiagnostics(checks, ctx, url);
|
||||
|
||||
const method = asString(config.method, "POST").trim().toUpperCase() || "POST";
|
||||
checks.push({
|
||||
code: "openclaw_method_configured",
|
||||
|
||||
Reference in New Issue
Block a user