This commit is contained in:
@@ -261,6 +261,41 @@ export interface ToolContext {
|
||||
* then resumes the SAME movement. Mirrors pendingToolApproval.
|
||||
*/
|
||||
pendingSubtaskWait?: boolean;
|
||||
/**
|
||||
* Package-request mechanism: recorder for agent-declared Python package
|
||||
* requests (RequestPackage). Bound by the worker (task/job/space) ONLY when
|
||||
* the feature is enabled AND the run has a resolvable space. Undefined =>
|
||||
* feature unavailable for this run (RequestPackage records nothing and tells
|
||||
* the agent to proceed). piece-runner wraps it to inject piece + movement.
|
||||
*/
|
||||
recordPackageRequest?: (req: {
|
||||
spec: string;
|
||||
normalizedName: string;
|
||||
reason?: string | null;
|
||||
status?: 'pending' | 'approved' | 'denied' | 'auto_denied';
|
||||
}) => void;
|
||||
/**
|
||||
* Package-request mechanism: packages already installed in this workspace's
|
||||
* overlay (name→canonical spec, from the space desired-state at job start).
|
||||
* Version-aware: a pinned request (`name==version`) is only "already
|
||||
* installed" on an exact spec match; a bare-name request matches any version.
|
||||
* Lets RequestPackage short-circuit (and after a resume, recognise the
|
||||
* just-approved one). Undefined when the feature is off.
|
||||
*/
|
||||
installedPackages?: Array<{ name: string; spec: string }>;
|
||||
/**
|
||||
* Package-request mechanism: PEP 503 normalized names already declined
|
||||
* (denied / auto_denied) for THIS job. RequestPackage short-circuits a
|
||||
* re-request for one of these instead of re-parking — otherwise a deny would
|
||||
* loop (deny → movement re-runs → re-request → park). Undefined => none.
|
||||
*/
|
||||
declinedPackages?: string[];
|
||||
/**
|
||||
* Set by RequestPackage to signal the movement loop to pause (waiting_human)
|
||||
* for inline approval of the named package. Read + reset by agent-loop.
|
||||
* Mirrors pendingToolApproval.
|
||||
*/
|
||||
pendingPackageApproval?: { spec: string } | null;
|
||||
/** Per-task option: when true, MCP tools are not loaded/dispatched. */
|
||||
mcpDisabled?: boolean;
|
||||
/** Per-task option: when true, skill index is not injected into the system prompt. */
|
||||
@@ -920,8 +955,8 @@ export function checkBlockedInstallPatterns(command: string): void {
|
||||
throw new Error(
|
||||
`Package installation is not available in the sandbox. ` +
|
||||
`These are preinstalled and importable: ${PREINSTALLED_HINT}. ` +
|
||||
`If you need another package, ask an admin to add it to ` +
|
||||
`runtime/python-requirements.txt and rebuild — do not retry the install.`
|
||||
`If you need another package, request it with RequestPackage({ name: "<pkg>", reason: "..." }) ` +
|
||||
`— an approver installs it into this workspace and the run resumes. Do not retry the install here.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1876,7 +1911,21 @@ function executeGrep(input: Record<string, unknown>, ctx: ToolContext): ToolResu
|
||||
if (results.length === 0) {
|
||||
return { output: '(no matches)', isError: false };
|
||||
}
|
||||
return { output: results.join('\n'), isError: false };
|
||||
// Read と Bash は予算切り詰めがあるのに Grep だけ無制限だった。緩いパターン
|
||||
// 1回で数十万文字が会話に流れ込み、プロンプトを preflight 上限際まで押し込む
|
||||
// 起爆剤になっていたので、同じトークン予算で切り詰める。
|
||||
const budgetTokens = getToolOutputBudgetTokens(ctx);
|
||||
const raw = results.join('\n');
|
||||
const { text, truncated } = truncateToBudget(raw, budgetTokens, {
|
||||
sourceLabel: `Grep 結果 (pattern: ${pattern})`,
|
||||
totalLines: results.length,
|
||||
continuationHint:
|
||||
'マッチが多すぎます。pattern をより具体的にする、glob でファイルを絞る、path でディレクトリを絞る、のいずれかで検索範囲を狭めてください',
|
||||
});
|
||||
if (truncated) {
|
||||
logger.info(`[grep] truncated matches=${results.length} original_chars=${raw.length} budget_tokens=${budgetTokens}`);
|
||||
}
|
||||
return { output: text, isError: false };
|
||||
}
|
||||
|
||||
// コアツールを実行 (Read, Write, Edit, Bash, Glob, Grep)
|
||||
|
||||
Reference in New Issue
Block a user