Agents: include runtime shell (#1835)

* Agents: include runtime shell

* Agents: fix compact runtime build

* chore: fix CLAUDE.md formatting, security regex for secret

---------

Co-authored-by: Tak hoffman <takayukihoffman@gmail.com>
Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
main
Tak Hoffman 2026-02-07 11:32:31 -06:00 committed by GitHub
parent a4d5c7f673
commit f0722498a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 68 additions and 1 deletions

View File

@ -1 +1 @@
AGENTS.md AGENTS.md

View File

@ -11,6 +11,7 @@ import type { EmbeddedContextFile } from "../pi-embedded-helpers.js";
import { runExec } from "../../process/exec.js"; import { runExec } from "../../process/exec.js";
import { buildTtsSystemPromptHint } from "../../tts/tts.js"; import { buildTtsSystemPromptHint } from "../../tts/tts.js";
import { resolveDefaultModelForAgent } from "../model-selection.js"; import { resolveDefaultModelForAgent } from "../model-selection.js";
import { detectRuntimeShell } from "../shell-utils.js";
import { buildSystemPromptParams } from "../system-prompt-params.js"; import { buildSystemPromptParams } from "../system-prompt-params.js";
import { buildAgentSystemPrompt } from "../system-prompt.js"; import { buildAgentSystemPrompt } from "../system-prompt.js";
@ -226,6 +227,7 @@ export function buildSystemPrompt(params: {
node: process.version, node: process.version,
model: params.modelDisplay, model: params.modelDisplay,
defaultModel: defaultModelLabel, defaultModel: defaultModelLabel,
shell: detectRuntimeShell(),
}, },
}); });
const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : undefined; const ttsHint = params.config ? buildTtsSystemPromptHint(params.config) : undefined;

View File

@ -45,6 +45,7 @@ import { resolveSandboxContext } from "../sandbox.js";
import { repairSessionFileIfNeeded } from "../session-file-repair.js"; import { repairSessionFileIfNeeded } from "../session-file-repair.js";
import { guardSessionManager } from "../session-tool-result-guard-wrapper.js"; import { guardSessionManager } from "../session-tool-result-guard-wrapper.js";
import { acquireSessionWriteLock } from "../session-write-lock.js"; import { acquireSessionWriteLock } from "../session-write-lock.js";
import { detectRuntimeShell } from "../shell-utils.js";
import { import {
applySkillEnvOverrides, applySkillEnvOverrides,
applySkillEnvOverridesFromSnapshot, applySkillEnvOverridesFromSnapshot,
@ -308,6 +309,7 @@ export async function compactEmbeddedPiSessionDirect(
arch: os.arch(), arch: os.arch(),
node: process.version, node: process.version,
model: `${provider}/${modelId}`, model: `${provider}/${modelId}`,
shell: detectRuntimeShell(),
channel: runtimeChannel, channel: runtimeChannel,
capabilities: runtimeCapabilities, capabilities: runtimeCapabilities,
channelActions, channelActions,

View File

@ -49,6 +49,7 @@ import { resolveSandboxRuntimeStatus } from "../../sandbox/runtime-status.js";
import { repairSessionFileIfNeeded } from "../../session-file-repair.js"; import { repairSessionFileIfNeeded } from "../../session-file-repair.js";
import { guardSessionManager } from "../../session-tool-result-guard-wrapper.js"; import { guardSessionManager } from "../../session-tool-result-guard-wrapper.js";
import { acquireSessionWriteLock } from "../../session-write-lock.js"; import { acquireSessionWriteLock } from "../../session-write-lock.js";
import { detectRuntimeShell } from "../../shell-utils.js";
import { import {
applySkillEnvOverrides, applySkillEnvOverrides,
applySkillEnvOverridesFromSnapshot, applySkillEnvOverridesFromSnapshot,
@ -331,6 +332,7 @@ export async function runEmbeddedAttempt(
node: process.version, node: process.version,
model: `${params.provider}/${params.modelId}`, model: `${params.provider}/${params.modelId}`,
defaultModel: defaultModelLabel, defaultModel: defaultModelLabel,
shell: detectRuntimeShell(),
channel: runtimeChannel, channel: runtimeChannel,
capabilities: runtimeCapabilities, capabilities: runtimeCapabilities,
channelActions, channelActions,

View File

@ -67,6 +67,63 @@ function resolveShellFromPath(name: string): string | undefined {
return undefined; return undefined;
} }
function normalizeShellName(value: string): string {
const trimmed = value.trim();
if (!trimmed) {
return "";
}
return path
.basename(trimmed)
.replace(/\.(exe|cmd|bat)$/i, "")
.replace(/[^a-zA-Z0-9_-]/g, "");
}
export function detectRuntimeShell(): string | undefined {
const overrideShell = process.env.CLAWDBOT_SHELL?.trim();
if (overrideShell) {
const name = normalizeShellName(overrideShell);
if (name) {
return name;
}
}
if (process.platform === "win32") {
if (process.env.POWERSHELL_DISTRIBUTION_CHANNEL) {
return "pwsh";
}
return "powershell";
}
const envShell = process.env.SHELL?.trim();
if (envShell) {
const name = normalizeShellName(envShell);
if (name) {
return name;
}
}
if (process.env.POWERSHELL_DISTRIBUTION_CHANNEL) {
return "pwsh";
}
if (process.env.BASH_VERSION) {
return "bash";
}
if (process.env.ZSH_VERSION) {
return "zsh";
}
if (process.env.FISH_VERSION) {
return "fish";
}
if (process.env.KSH_VERSION) {
return "ksh";
}
if (process.env.NU_VERSION || process.env.NUSHELL_VERSION) {
return "nu";
}
return undefined;
}
export function sanitizeBinaryOutput(text: string): string { export function sanitizeBinaryOutput(text: string): string {
const scrubbed = text.replace(/[\p{Format}\p{Surrogate}]/gu, ""); const scrubbed = text.replace(/[\p{Format}\p{Surrogate}]/gu, "");
if (!scrubbed) { if (!scrubbed) {

View File

@ -16,6 +16,7 @@ export type RuntimeInfoInput = {
node: string; node: string;
model: string; model: string;
defaultModel?: string; defaultModel?: string;
shell?: string;
channel?: string; channel?: string;
capabilities?: string[]; capabilities?: string[];
/** Supported message actions for the current channel (e.g., react, edit, unsend) */ /** Supported message actions for the current channel (e.g., react, edit, unsend) */

View File

@ -190,6 +190,7 @@ export function buildAgentSystemPrompt(params: {
node?: string; node?: string;
model?: string; model?: string;
defaultModel?: string; defaultModel?: string;
shell?: string;
channel?: string; channel?: string;
capabilities?: string[]; capabilities?: string[];
repoRoot?: string; repoRoot?: string;
@ -616,6 +617,7 @@ export function buildRuntimeLine(
node?: string; node?: string;
model?: string; model?: string;
defaultModel?: string; defaultModel?: string;
shell?: string;
repoRoot?: string; repoRoot?: string;
}, },
runtimeChannel?: string, runtimeChannel?: string,
@ -634,6 +636,7 @@ export function buildRuntimeLine(
runtimeInfo?.node ? `node=${runtimeInfo.node}` : "", runtimeInfo?.node ? `node=${runtimeInfo.node}` : "",
runtimeInfo?.model ? `model=${runtimeInfo.model}` : "", runtimeInfo?.model ? `model=${runtimeInfo.model}` : "",
runtimeInfo?.defaultModel ? `default_model=${runtimeInfo.defaultModel}` : "", runtimeInfo?.defaultModel ? `default_model=${runtimeInfo.defaultModel}` : "",
runtimeInfo?.shell ? `shell=${runtimeInfo.shell}` : "",
runtimeChannel ? `channel=${runtimeChannel}` : "", runtimeChannel ? `channel=${runtimeChannel}` : "",
runtimeChannel runtimeChannel
? `capabilities=${runtimeCapabilities.length > 0 ? runtimeCapabilities.join(",") : "none"}` ? `capabilities=${runtimeCapabilities.length > 0 ? runtimeCapabilities.join(",") : "none"}`