





















@@ -27,20 +27,25 @@ import {
2727import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
2828import { createSubsystemLogger } from "../../logging/subsystem.js";
2929import { collectEnabledInsecureOrDangerousFlags } from "../../security/dangerous-config-flags.js";
30+import { parseConfigPathArrayIndex } from "../../shared/path-array-index.js";
3031import { optionalNonNegativeIntegerSchema, stringEnum } from "../schema/typebox.js";
3132import {
3233type AnyAgentTool,
3334jsonResult,
3435readNonNegativeIntegerParam,
3536readStringArrayParam,
3637readStringParam,
38+textResult,
39+ToolInputError,
3740} from "./common.js";
3841import { gatewayCallOptionSchemaProperties } from "./gateway-schema.js";
3942import { callGatewayTool, readGatewayCallOptions } from "./gateway.js";
40434144const log = createSubsystemLogger("gateway-tool");
42454346const DEFAULT_UPDATE_TIMEOUT_MS = 20 * 60_000;
47+// Keep complete JSON below the smallest default tool-result presentation budget.
48+const MAX_GATEWAY_CONFIG_GET_TEXT_CHARS = 12_000;
4449const CONFIG_SCHEMA_PATH_NOT_FOUND_MESSAGE = "config schema path not found";
4550// Per SECURITY.md the model/agent itself is not a trusted principal.
4651// `assertGatewayConfigMutationAllowed` is the explicit model -> operator
@@ -111,6 +116,66 @@ function getSnapshotConfig(snapshot: unknown): Record<string, unknown> {
111116return config as Record<string, unknown>;
112117}
113118119+function splitGatewayConfigGetPath(path: string): string[] {
120+return path
121+.trim()
122+.replace(/\[(\d+)\]/g, ".$1")
123+.split(".")
124+.filter(Boolean);
125+}
126+127+function resolveGatewayConfigGetPath(config: Record<string, unknown>, path: string): unknown {
128+const parts = splitGatewayConfigGetPath(path);
129+if (parts.length === 0) {
130+return undefined;
131+}
132+let current: unknown = config;
133+for (const part of parts) {
134+if (!current || typeof current !== "object") {
135+return undefined;
136+}
137+if (Array.isArray(current)) {
138+const index = parseConfigPathArrayIndex(part);
139+if (index === undefined || index >= current.length) {
140+return undefined;
141+}
142+current = current[index];
143+continue;
144+}
145+if (!Object.hasOwn(current, part)) {
146+return undefined;
147+}
148+current = (current as Record<string, unknown>)[part];
149+}
150+return current;
151+}
152+153+function selectGatewayConfigGetResult(snapshot: unknown, path: string | undefined): unknown {
154+if (!path) {
155+return snapshot;
156+}
157+const value = resolveGatewayConfigGetPath(getSnapshotConfig(snapshot), path);
158+if (value === undefined) {
159+throw new ToolInputError(`config path not found: ${path}`);
160+}
161+const hash = readStringValue((snapshot as { hash?: unknown }).hash);
162+return {
163+ ...(hash ? { hash } : {}),
164+ path,
165+config: value,
166+};
167+}
168+169+function createGatewayConfigGetToolResult(result: unknown) {
170+const text = JSON.stringify({ ok: true, result }, null, 2);
171+if (text.length > MAX_GATEWAY_CONFIG_GET_TEXT_CHARS) {
172+throw new ToolInputError(
173+"config.get response is too large; use path to request a narrower config subtree",
174+);
175+}
176+return textResult(text, { ok: true });
177+}
178+114179// Direct RPC callers need the validated config echoed after writes; the
115180// agent-facing gateway tool does not, and replaying it bloats transcripts.
116181function stripConfigWriteResultPayload(result: unknown): unknown {
@@ -367,7 +432,7 @@ const GatewayToolSchema = Type.Object({
367432continuationMessage: Type.Optional(Type.String()),
368433// config.get, config.schema.lookup, config.apply, update.run
369434 ...gatewayCallOptionSchemaProperties(),
370-// config.schema.lookup
435+// config.get, config.schema.lookup
371436path: Type.Optional(Type.String()),
372437// config.apply, config.patch
373438raw: Type.Optional(Type.String()),
@@ -498,8 +563,10 @@ export function createGatewayTool(opts?: {
498563};
499564500565if (action === "config.get") {
501-const result = await callGatewayTool("config.get", gatewayOpts, {});
502-return jsonResult({ ok: true, result });
566+const path = readStringParam(params, "path");
567+const snapshot = await callGatewayTool("config.get", gatewayOpts, {});
568+const result = selectGatewayConfigGetResult(snapshot, path);
569+return createGatewayConfigGetToolResult(result);
503570}
504571if (action === "config.schema.lookup") {
505572const path = readStringParam(params, "path", {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。