feat(adapter): agent instructions file support and docs:dev script
Add instructionsFilePath config to Claude and Codex adapters, allowing agents to load external instruction files appended to the system prompt. Claude uses --append-system-prompt-file; Codex prepends file contents to the prompt. Add docs:dev script for local Mintlify preview. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,8 @@
|
|||||||
"db:migrate": "pnpm --filter @paperclip/db migrate",
|
"db:migrate": "pnpm --filter @paperclip/db migrate",
|
||||||
"secrets:migrate-inline-env": "tsx scripts/migrate-inline-env-secrets.ts",
|
"secrets:migrate-inline-env": "tsx scripts/migrate-inline-env-secrets.ts",
|
||||||
"db:backup": "./scripts/backup-db.sh",
|
"db:backup": "./scripts/backup-db.sh",
|
||||||
"paperclip": "node cli/node_modules/tsx/dist/cli.mjs cli/src/index.ts"
|
"paperclip": "node cli/node_modules/tsx/dist/cli.mjs cli/src/index.ts",
|
||||||
|
"docs:dev": "cd docs && npx mintlify dev"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.7.3",
|
||||||
|
|||||||
@@ -267,6 +267,8 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
|||||||
const chrome = asBoolean(config.chrome, false);
|
const chrome = asBoolean(config.chrome, false);
|
||||||
const maxTurns = asNumber(config.maxTurnsPerRun, 0);
|
const maxTurns = asNumber(config.maxTurnsPerRun, 0);
|
||||||
const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, false);
|
const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, false);
|
||||||
|
const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||||
|
const instructionsFileDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : "";
|
||||||
|
|
||||||
const runtimeConfig = await buildClaudeRuntimeConfig({
|
const runtimeConfig = await buildClaudeRuntimeConfig({
|
||||||
runId,
|
runId,
|
||||||
@@ -321,6 +323,13 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
|||||||
if (model) args.push("--model", model);
|
if (model) args.push("--model", model);
|
||||||
if (effort) args.push("--effort", effort);
|
if (effort) args.push("--effort", effort);
|
||||||
if (maxTurns > 0) args.push("--max-turns", String(maxTurns));
|
if (maxTurns > 0) args.push("--max-turns", String(maxTurns));
|
||||||
|
if (instructionsFilePath) {
|
||||||
|
args.push("--append-system-prompt-file", instructionsFilePath);
|
||||||
|
args.push(
|
||||||
|
"--append-system-prompt",
|
||||||
|
`The above agent instructions were loaded from ${instructionsFilePath}. Resolve any relative file references from ${instructionsFileDir}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
args.push("--add-dir", skillsDir);
|
args.push("--add-dir", skillsDir);
|
||||||
if (extraArgs.length > 0) args.push(...extraArgs);
|
if (extraArgs.length > 0) args.push(...extraArgs);
|
||||||
return args;
|
return args;
|
||||||
|
|||||||
@@ -230,8 +230,30 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
|||||||
`[paperclip] Codex session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`,
|
`[paperclip] Codex session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
|
||||||
|
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}. ` +
|
||||||
|
`Resolve any relative file references from ${instructionsDir}.\n\n`;
|
||||||
|
await onLog(
|
||||||
|
"stderr",
|
||||||
|
`[paperclip] Loaded agent instructions file: ${instructionsFilePath}\n`,
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
const reason = err instanceof Error ? err.message : String(err);
|
||||||
|
await onLog(
|
||||||
|
"stderr",
|
||||||
|
`[paperclip] Warning: could not read agent instructions file "${instructionsFilePath}": ${reason}\n`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
const template = sessionId ? promptTemplate : bootstrapTemplate;
|
const template = sessionId ? promptTemplate : bootstrapTemplate;
|
||||||
const prompt = renderTemplate(template, {
|
const renderedPrompt = renderTemplate(template, {
|
||||||
agentId: agent.id,
|
agentId: agent.id,
|
||||||
companyId: agent.companyId,
|
companyId: agent.companyId,
|
||||||
runId,
|
runId,
|
||||||
@@ -240,6 +262,7 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
|
|||||||
run: { id: runId, source: "on_demand" },
|
run: { id: runId, source: "on_demand" },
|
||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
const prompt = `${instructionsPrefix}${renderedPrompt}`;
|
||||||
|
|
||||||
const buildArgs = (resumeSessionId: string | null) => {
|
const buildArgs = (resumeSessionId: string | null) => {
|
||||||
const args = ["exec", "--json"];
|
const args = ["exec", "--json"];
|
||||||
|
|||||||
Reference in New Issue
Block a user