mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-10-04 07:16:52 +02:00
* feat(worker): record token, cache, and turn usage per agent * feat: replace model tiers with a single SHANNON_AI_MODEL across five providers * feat(cli): rebuild the setup wizard for provider and model selection * docs: document single-model selection and supported providers * feat(worker): use chat completions for OpenAI behind a custom base URL * feat: add SHANNON_AI_OPENAI_FORMAT to pick the wire API for OpenAI gateways * refactor(cli): drop endpoint path hints from the gateway format picker * feat(worker): enable pi in-session provider retry with retry-after backoff * refactor(worker): hand provider error classification to pi and drop the Anthropic ladders * refactor: remove the subscription retry preset and pipeline config section * fix(worker): validate Bedrock credentials with the same live probe as other providers * feat(worker): render the report from structured findings instead of agent-written markdown * fix(worker): dispose the credential probe session on every path * fix(worker): refuse to replace the assembled report with an empty one * refactor(worker): catch post-processing throws across the whole finalization block * revert(worker): drop the report zero-findings guard * docs(worker): correct the retry split and Bedrock credential claims * docs: regenerate llms-full.txt from current sources * feat(cli): build and run the npx flow from a clone * refactor(cli): flatten the setup summary output * feat(cli): reject runs with more than one provider configured * fix(worker): say a rejected bash call never ran * chore(cli): drop grok-4.3 and gpt-5.6-luna from the setup suggestions * feat(worker): capture structured finding locations for SARIF output * fix(worker): enumerate queue confidence so the report inherits it verbatim * feat(worker): give the reporting phase a mode-specific output schema * feat(worker): emit a SARIF 2.1.0 log for exploitative runs * fix(worker): correct SARIF locations and defer fingerprinting to the upload action * fix(worker): drop the confidence suffix from the analysis-mode summary list * feat(worker): give exploit findings a dedicated code location field * feat(worker): carry structured code locations from the vuln queue to the report * fix(worker): join code locations from the vuln queue instead of re-asking agents * fix(worker): spell out the finding_id to category mapping in the tool schema * feat: drop Google/Gemini as a supported AI provider * fix(worker): stop asking the report agent for code locations * docs: correct the provider list and drop the removed rate-limit settings * docs: add provider cyber safeguards and suggested models per provider * docs: document the SARIF output and the report rating thresholds
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
/**
|
|
* pi extension: enforce a bounded timeout on every `bash` tool call.
|
|
*
|
|
* pi's built-in bash tool accepts an optional `timeout` (in seconds) but applies
|
|
* NO default and NO upper bound — an unbounded command (e.g. a `playwright-cli`
|
|
* browser action that never returns) hangs the agent indefinitely. This extension
|
|
* registers a `tool_call` pre-execution handler that blocks any `bash` invocation
|
|
* that omits `timeout` or sets it above the maximum, returning a message that tells
|
|
* the model how to re-run the command correctly.
|
|
*/
|
|
|
|
import type { ExtensionAPI, ToolCallEvent, ToolCallEventResult } from '@earendil-works/pi-coding-agent';
|
|
import { isToolCallEventType } from '@earendil-works/pi-coding-agent';
|
|
|
|
/** Recommended timeout (seconds) suggested to the model when it omits one. */
|
|
const DEFAULT_TIMEOUT_SECONDS = 120;
|
|
|
|
/** Hard upper bound (seconds) a single bash command may run. */
|
|
const MAX_TIMEOUT_SECONDS = 600;
|
|
|
|
function evaluateBashTimeout(timeout: number | undefined): ToolCallEventResult | undefined {
|
|
const hasValidTimeout = typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0;
|
|
if (!hasValidTimeout) {
|
|
return {
|
|
block: true,
|
|
reason: `A timeout in seconds is required for the bash tool. The bash tool was not executed. Use the default of ${DEFAULT_TIMEOUT_SECONDS} seconds, or up to a maximum of ${MAX_TIMEOUT_SECONDS} seconds.`,
|
|
};
|
|
}
|
|
|
|
if (timeout > MAX_TIMEOUT_SECONDS) {
|
|
return {
|
|
block: true,
|
|
reason: `bash 'timeout' ${timeout}s exceeds max ${MAX_TIMEOUT_SECONDS}s. Default ${DEFAULT_TIMEOUT_SECONDS}s, max ${MAX_TIMEOUT_SECONDS}s.`,
|
|
};
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
export default function bashTimeoutExtension(pi: ExtensionAPI): void {
|
|
pi.on('tool_call', (event: ToolCallEvent): ToolCallEventResult | undefined => {
|
|
if (!isToolCallEventType('bash', event)) {
|
|
return undefined;
|
|
}
|
|
return evaluateBashTimeout(event.input.timeout);
|
|
});
|
|
}
|