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
2 changes: 1 addition & 1 deletion AGENTS-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Stable Contracts and Security Control Plane 的边界以
| 2 | 产品组装层 | `src/crates/assembly` | 兼容导出、产品能力选择、product-full 接线、不可变内置 Agent 内容、adapter/service 注册和生态无关的来源协调 | `agent-content`, `core`, `external-sources`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) |
| 3 | 适配层 | `src/crates/adapters` | AI/transport/WebDriver 协议 adapter、外部 AI work source adapter(OpenCode/Claude Code/Codex)和外部 provider 转换 | `agent-runtime-ipc`、`ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
| 4 | 服务实现层 | `src/crates/services` | 可复用 OS、filesystem、terminal、MCP、remote、git、watch、process、session persistence primitives、network 和 MiniApp runtime IO 实现 | `services-core`, `services-integrations`, `relay-service`, `page-function-runtime`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) |
| 5 | 执行原语层 | `src/crates/execution` | 可移植 Agent Runtime、命名工作流策略、stream、插件运行时客户端、typed-service、tool-contract、tool-group 和 tool-execution 构件 | `agent-runtime`, `agent-workflows`, `agent-stream`, `tool-contracts`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution`, `tool-call-jsonrepair` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 5 | 执行原语层 | `src/crates/execution` | 可移植 Agent Runtime、命名工作流策略、stream、插件运行时客户端、typed-service、tool-contract、tool-group 和 tool-execution 构件 | `agent-runtime`, `agent-workflows`, `agent-stream`, `tool-contracts`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 6 | 稳定契约与产品领域层 | `src/crates/contracts` | 跨层共享 DTO、事件形状、runtime port、产品领域契约和策略 | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) |

边界规则:
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Keep crate dependencies inside each layer to the smallest set needed.
| 2 | Product assembly | `src/crates/assembly` | Compatibility exports, product capability selection, product-full wiring, immutable built-in Agent content, adapter/service registration, and ecosystem-neutral source coordination | `agent-content`, `core`, `external-sources`, `product-capabilities` | [AGENTS.md](src/crates/assembly/AGENTS.md) |
| 3 | Adapters | `src/crates/adapters` | AI/transport/WebDriver protocol adapters, external AI work source adapters (OpenCode/Claude Code/Codex), and external-provider translation | `agent-runtime-ipc`, `ai-adapters`, `opencode-adapter`, `claude-code-adapter`, `codex-adapter`, `static-hook-support`, `transport`, `webdriver` | [AGENTS.md](src/crates/adapters/AGENTS.md) |
| 4 | Services | `src/crates/services` | Reusable OS, filesystem, terminal, MCP, remote, git, watch, process, session persistence primitives, MiniApp runtime IO, and network implementations | `services-core`, `services-integrations`, `miniapp-market-service`, `relay-service`, `page-function-runtime`, `terminal` | [AGENTS.md](src/crates/services/AGENTS.md) |
| 5 | Execution primitives | `src/crates/execution` | Portable Agent Runtime, named-workflow policy, stream, plugin runtime client, typed-service, tool-contract, tool-group, and tool-execution building blocks | `agent-runtime`, `agent-workflows`, `agent-stream`, `tool-contracts`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution`, `tool-call-jsonrepair` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 5 | Execution primitives | `src/crates/execution` | Portable Agent Runtime, named-workflow policy, stream, plugin runtime client, typed-service, tool-contract, tool-group, and tool-execution building blocks | `agent-runtime`, `agent-workflows`, `agent-stream`, `tool-contracts`, `plugin-runtime-client`, `runtime-services`, `tool-provider-groups`, `tool-execution` | [AGENTS.md](src/crates/execution/AGENTS.md) |
| 6 | Stable contracts and product domains | `src/crates/contracts` | Shared DTOs, event shapes, runtime ports, and product domain contracts/policies | `core-types`, `events`, `runtime-ports`, `product-domains` | [AGENTS.md](src/crates/contracts/AGENTS.md) |

Boundary rules:
Expand Down
16 changes: 7 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ members = [
"src/crates/execution/agent-runtime",
"src/crates/execution/agent-workflows",
"src/crates/execution/agent-stream",
"src/crates/execution/tool-call-jsonrepair",
"src/crates/execution/tool-contracts",
"src/crates/execution/plugin-runtime-client",
"src/crates/execution/runtime-services",
Expand Down Expand Up @@ -97,6 +96,7 @@ futures-util = "0.3.31"
# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
jsonrepair-rs = { version = "0.2.6", default-features = false }
serde_yaml = "0.9"

# Document conversion
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/product-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ block-beta
| Assembly | `src/crates/assembly/*` | `agent-content`、`core`、`external-sources`、`product-capabilities` |
| Adapters | `src/crates/adapters/*` | `agent-runtime-ipc`、`ai-adapters`、`claude-code-adapter`、`codex-adapter`、`dsh-adapter`、`opencode-adapter`、`static-hook-support`、`transport`、`webdriver` |
| Services | `src/crates/services/*` | `services-core`、`services-integrations`、`miniapp-market-service`、`skin-market-service`、`relay-service`、`page-function-runtime`、`terminal` |
| Execution | `src/crates/execution/*` | `agent-runtime`、`agent-workflows`、`agent-stream`、`plugin-runtime-client`、`runtime-services`、`tool-contracts`、`tool-provider-groups`、`tool-execution`、`tool-call-jsonrepair` |
| Execution | `src/crates/execution/*` | `agent-runtime`、`agent-workflows`、`agent-stream`、`plugin-runtime-client`、`runtime-services`、`tool-contracts`、`tool-provider-groups`、`tool-execution` |
| Contracts | `src/crates/contracts/*` | `core-types`、`events`、`runtime-ports`、`product-domains` |

Installer、E2E 以及 MiniApp/Skin market server 和对应 service 在 Level 0 图中分别归入交付入口、测试范围或 Services 家族,不作为独立架构模块。
Expand Down
1 change: 0 additions & 1 deletion scripts/core-boundaries/rules/crate-layout.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const crateLayoutRules = [
{ crateName: 'agent-runtime', layer: 'execution', path: 'src/crates/execution/agent-runtime' },
{ crateName: 'agent-workflows', layer: 'execution', path: 'src/crates/execution/agent-workflows' },
{ crateName: 'agent-stream', layer: 'execution', path: 'src/crates/execution/agent-stream' },
{ crateName: 'tool-call-jsonrepair', layer: 'execution', path: 'src/crates/execution/tool-call-jsonrepair' },
{ crateName: 'agent-tools', layer: 'execution', path: 'src/crates/execution/tool-contracts' },
{ crateName: 'plugin-runtime-client', layer: 'execution', path: 'src/crates/execution/plugin-runtime-client' },
{ crateName: 'runtime-services', layer: 'execution', path: 'src/crates/execution/runtime-services' },
Expand Down
2 changes: 0 additions & 2 deletions scripts/core-boundaries/rules/crate-rules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const agentRuntimeIpcForbiddenDeps = [
'openbitfun-services-core',
'openbitfun-services-integrations',
'openbitfun-static-hook-support',
'openbitfun-tool-call-jsonrepair',
'openbitfun-tool-packs',
'openbitfun-webdriver',
'terminal-core',
Expand All @@ -44,7 +43,6 @@ export const noCoreDependencyCrates = [
'events',
'ai-adapters',
'agent-stream',
'tool-call-jsonrepair',
'agent-runtime',
'agent-workflows',
'agent-runtime-ipc',
Expand Down
1 change: 0 additions & 1 deletion src/crates/execution/AGENTS-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
| `runtime-services` | Typed runtime service assembly 和 service availability facts | [AGENTS.md](runtime-services/AGENTS.md) |
| `tool-provider-groups` | Tool provider group facts 和 product-full tool group composition;Cargo package 仍为 `openbitfun-tool-packs` | [AGENTS.md](tool-provider-groups/AGENTS.md) |
| `tool-execution` | 底层 file/search/tool IO helper、ExecCommand presentation facts、Computer Use loop/retry policy、prompt-safe tool context facts 和 provider-neutral tool runtime policy;Cargo package 仍为 `tool-runtime` | [AGENTS.md](tool-execution/AGENTS.md) |
| `tool-call-jsonrepair` | 流式 tool-call 参数的有界 JSON 修复(`jsonrepair-rs` 本地 fork,采用不把 `#`/`//`/`/* */` 视为注释的 tool-argument profile);Cargo package 仍为 `openbitfun-tool-call-jsonrepair` | [README.md](tool-call-jsonrepair/README.md) |

## 放置规则

Expand Down
1 change: 0 additions & 1 deletion src/crates/execution/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ delivery form.
| `runtime-services` | Typed runtime service assembly and service availability facts | [AGENTS.md](runtime-services/AGENTS.md) |
| `tool-provider-groups` | Tool provider group facts and product-full tool group composition. Cargo package remains `openbitfun-tool-packs`. | [AGENTS.md](tool-provider-groups/AGENTS.md) |
| `tool-execution` | Low-level file/search/tool IO helpers, ExecCommand presentation facts, Computer Use loop/retry policies, prompt-safe tool context facts, and provider-neutral tool runtime policies. Cargo package remains `tool-runtime`. | [AGENTS.md](tool-execution/AGENTS.md) |
| `tool-call-jsonrepair` | Guarded JSON repair for streamed tool-call arguments (local fork of `jsonrepair-rs` with a tool-argument profile that does not treat `#`/`//`/`/* */` as comments). Cargo package remains `openbitfun-tool-call-jsonrepair`. | [README.md](tool-call-jsonrepair/README.md) |

## Placement Rules

Expand Down
9 changes: 9 additions & 0 deletions src/crates/execution/agent-stream/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ portable stream contracts.
orchestration behavior here.
- Stream contract changes must preserve ordering, tool-call reconstruction,
reasoning/thinking fields, usage accounting, and malformed-chunk handling.
- Tool argument syntax repair uses upstream `jsonrepair-rs` with
`preserve_comment_markers` and `decode_unquoted_escapes` enabled. Keep repair
gated by the setting and a confirmed normal tool-use completion, then parse
and validate the candidate through the existing pipeline. Schema-guided
correction is not enabled. Write close-only recovery remains separate.
- Escape decoding preserves the existing model-argument policy: an unquoted
literal Windows path containing `\n` or `\t` is ambiguous and will decode
those escapes. Use properly escaped JSON paths; do not infer path semantics
from the controller OS, since the runtime and workspace may be remote.

## Verification

Expand Down
2 changes: 1 addition & 1 deletion src/crates/execution/agent-stream/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async-trait = { workspace = true }
openbitfun-events = { path = "../../contracts/events" }
openbitfun-core-types = { path = "../../contracts/core-types" }
futures = { workspace = true }
openbitfun-tool-call-jsonrepair = { path = "../tool-call-jsonrepair" }
jsonrepair-rs = { workspace = true }
log = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down
112 changes: 111 additions & 1 deletion src/crates/execution/agent-stream/src/tool_call_accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,13 @@ impl PendingToolCall {
} else if options.allow_normal_tool_json_repair
&& options.completion.permits_normal_tool_json_repair()
{
// Keep Markdown markers and decode model-emitted JSON escapes.
// Literal backslashes must be escaped or inside valid JSON strings.
let repair_options = jsonrepair_rs::RepairOptions::new()
.with_preserve_comment_markers(true)
.with_decode_unquoted_escapes(true);
let repaired =
openbitfun_tool_call_jsonrepair::repair_tool_call_json(&raw_arguments)
jsonrepair_rs::jsonrepair_with_options(&raw_arguments, repair_options)
.ok()
.and_then(|candidate| {
Self::parse_arguments(&tool_name, &candidate).ok()
Expand Down Expand Up @@ -1210,6 +1215,111 @@ mod tests {
);
}

#[test]
fn normal_tool_repair_preserves_content_and_escaped_paths() {
let cases = [
(
r##"{"content": # Heading\nSub"}"##,
json!({"content": "# Heading\nSub"}),
),
(
r#"{"content": // Heading\nSub}"#,
json!({"content": "// Heading\nSub"}),
),
(
r#"{"content": /* Heading\nSub */}"#,
json!({"content": "/* Heading\nSub */"}),
),
(
r#"{"content": text // example}"#,
json!({"content": "text // example"}),
),
(
r#"{"content": text /* example */}"#,
json!({"content": "text /* example */"}),
),
(
r#"{"content": prefix\"quote\"suffix}"#,
json!({"content": "prefix\"quote\"suffix"}),
),
(
r#"{"path": C:\\new\\table.txt}"#,
json!({"path": r"C:\new\table.txt"}),
),
(
r#"{"path":"C:\\new\\table.txt" "line_end":4}"#,
json!({"path": r"C:\new\table.txt", "line_end": 4}),
),
(
r#"{"path":"/home/user/project/file.txt" "line_end":4}"#,
json!({"path": "/home/user/project/file.txt", "line_end": 4}),
),
(r#"{"path": src/main.rs}"#, json!({"path": "src/main.rs"})),
(
r#"{"content": value\uD83D\uDE00}"#,
json!({"content": "value\u{1f600}"}),
),
(
r##"{"content":"# Heading\nhttps:/"##,
json!({"content": "# Heading\nhttps:/"}),
),
];

for (raw, expected) in cases {
let mut pending = PendingToolCall::default();
pending.start_new("call_content".to_string(), Some("tool_a".to_string()));
pending.append_arguments(raw);
let finalized = pending
.finalize_with_options(
ToolCallBoundary::FinishReason,
ToolCallFinalizeOptions {
completion: ToolCallCompletion::NormalToolUse,
allow_normal_tool_json_repair: true,
},
)
.expect("finalized tool");

assert!(!finalized.is_error, "raw={raw:?}");
assert_eq!(finalized.arguments, expected, "raw={raw:?}");
assert_eq!(finalized.raw_arguments, raw);
assert!(finalized.parse_error.is_some());
assert_eq!(
finalized.repair_kind,
ToolArgumentRepairKind::PermissiveNormalToolJsonRepair
);
}
}

#[test]
fn normal_tool_repair_rejects_invalid_content() {
for raw in [
r#"{"value":+e1}"#,
"{\"items\":[\u{000c}",
r#"{"content": value\uD800}"#,
r#"{"content": value\uDC00}"#,
r#"{"content": value\uD800\u0041}"#,
"{\"content\": # Heading\n## Sub\n}",
] {
let mut pending = PendingToolCall::default();
pending.start_new("call_invalid".to_string(), Some("tool_a".to_string()));
pending.append_arguments(raw);
let finalized = pending
.finalize_with_options(
ToolCallBoundary::FinishReason,
ToolCallFinalizeOptions {
completion: ToolCallCompletion::NormalToolUse,
allow_normal_tool_json_repair: true,
},
)
.expect("finalized tool");

assert!(finalized.is_error, "raw={raw:?}");
assert_eq!(finalized.arguments, json!({}));
assert_eq!(finalized.repair_kind, ToolArgumentRepairKind::None);
assert!(finalized.parse_error.is_some());
}
}

#[test]
fn non_write_repair_is_disabled_by_default() {
let mut pending = PendingToolCall::default();
Expand Down
27 changes: 0 additions & 27 deletions src/crates/execution/tool-call-jsonrepair/Cargo.toml

This file was deleted.

21 changes: 0 additions & 21 deletions src/crates/execution/tool-call-jsonrepair/LICENSE

This file was deleted.

28 changes: 0 additions & 28 deletions src/crates/execution/tool-call-jsonrepair/README.md

This file was deleted.

Loading
Loading