Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/tw-config/tests/manual/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,8 @@ pub fn sections() -> Vec<Section> {
Kind::Obj("security.redact"),
Def::Section,
t(
"Outbound redaction (Secrets & privacy in the app): credentials and personal information anywhere in a request are replaced with placeholders before it leaves, or only recorded, rule by rule.",
"出站脱敏(应用里叫「密钥与隐私」):请求发出前,按每条规则把其中任何位置的凭据和个人信息替换为占位符,或只记录。",
"Outbound redaction (Secrets & privacy in the app): credentials and personal information in the text a request carries (messages, system prompts, reasoning, tool arguments and results, tool descriptions) are replaced with placeholders before it leaves, or only recorded, rule by rule. Identifiers, model names and other protocol fields are sent as they are.",
"出站脱敏(应用里叫「密钥与隐私」):请求发出前,按每条规则把其中正文(消息、系统提示、推理、工具调用的参数和结果、工具说明)里的凭据和个人信息替换为占位符,或只记录;id、模型名等协议字段原样发出。",
),
),
row(
Expand Down
14 changes: 11 additions & 3 deletions crates/tw-control/src/replay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ pub async fn quote(
will_redact: {
let rt = s.gateway.runtime();
let mode = rt.config.security.redact.mode;
mode.acts() && !tw_gateway::guard::find(mode, &rt.redact, &raw).is_empty()
let shape = tw_gateway::client_api::ClientApi::written(&row.path);
mode.acts() && !tw_gateway::guard::find(mode, &rt.redact, &raw, shape).is_empty()
},
pricing_date: book.table().date.clone(),
}))
Expand Down Expand Up @@ -312,8 +313,15 @@ pub async fn run(
let rt = s.gateway.runtime();
let ledger = tw_gateway::guard::ledger_for(&raw);
let (body, path) = renamed(&row, raw, &model);
let (body, ledger) =
tw_gateway::guard::replace(rt.config.security.redact.mode, &rt.redact, body, &ledger);
// 只在写出来的文字里换,按存下来的那条请求的路径认形状(见 `tw_gateway::guard`)
let shape = tw_gateway::client_api::ClientApi::written(&path);
let (body, ledger) = tw_gateway::guard::replace(
rt.config.security.redact.mode,
&rt.redact,
body,
&ledger,
shape,
);

let url = tw_gateway::forward::upstream_url(&provider.base_url, &path, None);
let started = Instant::now();
Expand Down
26 changes: 13 additions & 13 deletions crates/tw-dialect/src/caller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,26 @@ pub fn rewrite(dialect: Dialect, body: &mut Value, mut f: impl FnMut(&mut String
}

#[derive(Default)]
struct Collect {
pub(crate) struct Collect {
at: Vec<Step>,
out: Vec<Spot>,
pub(crate) out: Vec<Spot>,
}

impl Collect {
fn key(&mut self, k: &str, f: impl FnOnce(&mut Self)) {
pub(crate) fn key(&mut self, k: &str, f: impl FnOnce(&mut Self)) {
self.at.push(Step::Key(k.to_string()));
f(self);
self.at.pop();
}

fn index(&mut self, i: usize, f: impl FnOnce(&mut Self)) {
pub(crate) fn index(&mut self, i: usize, f: impl FnOnce(&mut Self)) {
self.at.push(Step::Index(i));
f(self);
self.at.pop();
}

/// 眼下这个位置上的值是一个非空字符串就记下
fn here(&mut self, v: &Value, in_tool_result: bool) {
pub(crate) fn here(&mut self, v: &Value, in_tool_result: bool) {
if v.as_str().is_some_and(|s| !s.is_empty()) {
self.out.push(Spot {
path: self.at.clone(),
Expand All @@ -144,15 +144,15 @@ impl Collect {
}

/// `v.k` 是一个非空字符串就记下
fn field(&mut self, v: &Value, k: &str, in_tool_result: bool) {
pub(crate) fn field(&mut self, v: &Value, k: &str, in_tool_result: bool) {
if let Some(x) = v.get(k) {
self.key(k, |c| c.here(x, in_tool_result));
}
}

/// `string | [{text}]` 形状的内容:中间表示用 `text_of` 读它,数组里**每一块**的
/// `text` 都算,不看块的类型
fn text_of(&mut self, v: &Value, in_tool_result: bool) {
pub(crate) fn text_of(&mut self, v: &Value, in_tool_result: bool) {
match v {
Value::String(_) => self.here(v, in_tool_result),
Value::Array(items) => {
Expand All @@ -167,7 +167,7 @@ impl Collect {
/// 一个值里的全部字符串。中间表示把它整个写成 JSON 文字的地方用(Gemini 的函数
/// 结果、Bedrock 的 `json` 结果):调用方的字在这些字符串里,键名和 JSON 的标点
/// 不是谁打的字
fn leaves(&mut self, v: &Value, in_tool_result: bool) {
pub(crate) fn leaves(&mut self, v: &Value, in_tool_result: bool) {
match v {
Value::String(_) => self.here(v, in_tool_result),
Value::Array(items) => {
Expand All @@ -185,11 +185,11 @@ impl Collect {
}
}

fn str_of<'a>(v: &'a Value, k: &str) -> Option<&'a str> {
pub(crate) fn str_of<'a>(v: &'a Value, k: &str) -> Option<&'a str> {
v.get(k).and_then(Value::as_str)
}

fn each<'a>(v: &'a Value, k: &str) -> impl Iterator<Item = (usize, &'a Value)> {
pub(crate) fn each<'a>(v: &'a Value, k: &str) -> impl Iterator<Item = (usize, &'a Value)> {
v.get(k)
.and_then(Value::as_array)
.map(Vec::as_slice)
Expand Down Expand Up @@ -257,7 +257,7 @@ fn anthropic_block(c: &mut Collect, b: &Value) {

/// `document` 块:`text` 来源的 `data`,`content` 来源的各块文字。base64 和 URL
/// 来源是文件,不是文字
fn anthropic_document(c: &mut Collect, b: &Value, in_tool_result: bool) {
pub(crate) fn anthropic_document(c: &mut Collect, b: &Value, in_tool_result: bool) {
let Some(src) = b.get("source") else {
return;
};
Expand All @@ -273,7 +273,7 @@ fn anthropic_document(c: &mut Collect, b: &Value, in_tool_result: bool) {
}

/// `search_result` 块:中间表示里是「标题、来源、正文」三段拼成的一段文字
fn anthropic_search_result(c: &mut Collect, b: &Value, in_tool_result: bool) {
pub(crate) fn anthropic_search_result(c: &mut Collect, b: &Value, in_tool_result: bool) {
c.field(b, "title", in_tool_result);
c.field(b, "source", in_tool_result);
if let Some(content) = b.get("content") {
Expand Down Expand Up @@ -394,7 +394,7 @@ fn responses_content(c: &mut Collect, content: &Value, in_tool_result: bool) {

/// Gemini 的字段名驼峰和下划线写法都认(`gemini::request::field`)。这个值写在哪个
/// 键下:先驼峰,再下划线
fn gemini_key(v: &Value, camel: &str) -> Option<String> {
pub(crate) fn gemini_key(v: &Value, camel: &str) -> Option<String> {
if v.get(camel).is_some() {
return Some(camel.to_string());
}
Expand Down
1 change: 1 addition & 0 deletions crates/tw-dialect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ pub mod responses;
pub mod think;
pub mod url;
pub mod usage;
pub mod written;
Loading
Loading