Skip to content

Commit 529986f

Browse files
authored
Merge pull request #34 from Lixtt/fix/config-token-limits
Improve packaged build, skill ACL, and config compatibility
2 parents 31b0d0a + 2abacae commit 529986f

15 files changed

Lines changed: 439 additions & 22 deletions

File tree

.github/setup-workspace.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ echo "Replacing path dependencies with crates.io versions..."
99

1010
# core/Cargo.toml — internal crate deps
1111
sed -i.bak \
12+
-e 's|a3s-common = { version = "0.1.1", path = "../../common" }|a3s-common = "0.1.1"|' \
1213
-e 's|a3s-common = { version = "0.1", path = "../../common" }|a3s-common = "0.1.1"|' \
1314
-e 's|a3s-memory = { version = "0.1.1", path = "../../memory" }|a3s-memory = "0.1.1"|' \
1415
-e 's|a3s-lane = { version = "0.4", path = "../../lane" }|a3s-lane = "0.4"|' \

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ default_model = "anthropic/claude-sonnet-4-20250514"
7878
7979
providers "anthropic" {
8080
apiKey = env("ANTHROPIC_API_KEY")
81+
82+
models "claude-sonnet-4-20250514" {
83+
limit = {
84+
context = 200000
85+
output = 8192
86+
}
87+
}
8188
}
8289
```
8390

@@ -1267,6 +1274,13 @@ default_model = "anthropic/claude-sonnet-4-20250514"
12671274
12681275
providers "anthropic" {
12691276
apiKey = env("ANTHROPIC_API_KEY")
1277+
1278+
models "claude-sonnet-4-20250514" {
1279+
limit = {
1280+
context = 200000
1281+
output = 8192
1282+
}
1283+
}
12701284
}
12711285
12721286
skill_dirs = ["./skills"]
@@ -1279,6 +1293,10 @@ ahp = {
12791293
}
12801294
```
12811295

1296+
Model token limits use the `limit = { context = ..., output = ... }` object as the canonical ACL shape.
1297+
The flat `maxTokens` and `contextTokens` fields are accepted only as deprecated
1298+
migration aliases and emit warnings.
1299+
12821300
---
12831301

12841302
## Development

core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ path = "src/lib.rs"
1313

1414
[dependencies]
1515
# Internal crates
16-
a3s-common = { version = "0.1", path = "../../common" }
16+
a3s-common = { version = "0.1.1", path = "../../common" }
1717
a3s-memory = { version = "0.1.1", path = "../../memory" }
1818
a3s-lane = { version = "0.4", path = "../../lane" }
1919
a3s-search = { version = "1.2.3", path = "../../search", default-features = false, features = ["lightpanda"] }

core/skills/code-review.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
name: code-review
33
description: Review code for best practices, bugs, and improvements
4+
allowed-tools: "grep(*), glob(*), read(*)"
45
kind: instruction
56
tags:
67
- review

core/skills/code-search.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
name: code-search
33
description: Search codebase for patterns, functions, or types
4+
allowed-tools: "grep(*), glob(*), read(*)"
45
kind: instruction
56
tags:
67
- search

core/skills/explain-code.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
name: explain-code
33
description: Explain how code works in clear, simple terms
4+
allowed-tools: "grep(*), glob(*), read(*)"
45
kind: instruction
56
tags:
67
- explain

core/skills/find-bugs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
name: find-bugs
33
description: Identify potential bugs, vulnerabilities, and code smells
4+
allowed-tools: "grep(*), glob(*), read(*)"
45
kind: instruction
56
tags:
67
- bugs

core/src/agent.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,15 +627,13 @@ impl SessionCommand for ToolCommand {
627627
async fn execute(&self) -> Result<Value> {
628628
// Check skill-based tool permissions
629629
if let Some(registry) = &self.skill_registry {
630-
let instruction_skills = registry.by_kind(crate::skills::SkillKind::Instruction);
631-
632630
// If there are instruction skills with tool restrictions, check permissions
633-
let has_restrictions = instruction_skills.iter().any(|s| s.allowed_tools.is_some());
631+
let restricting_skills = registry.global_tool_restricting_skills();
634632

635-
if has_restrictions {
633+
if !restricting_skills.is_empty() {
636634
let mut allowed = false;
637635

638-
for skill in &instruction_skills {
636+
for skill in &restricting_skills {
639637
if skill.is_tool_allowed(&self.tool_name) {
640638
allowed = true;
641639
break;

core/src/config/loader.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@ fn acl_usize_attr(block: &a3s_acl::Block, keys: &[&str]) -> Option<usize> {
5252
}
5353
}
5454

55+
fn acl_u32(value: &a3s_acl::Value) -> Option<u32> {
56+
match value {
57+
a3s_acl::Value::Number(value) if *value >= 0.0 => {
58+
Some((*value as usize).min(u32::MAX as usize) as u32)
59+
}
60+
_ => None,
61+
}
62+
}
63+
64+
fn acl_object_u32_attr(value: &a3s_acl::Value, key: &str) -> Option<u32> {
65+
match value {
66+
a3s_acl::Value::Object(pairs) => pairs
67+
.iter()
68+
.find_map(|(candidate, value)| (candidate == key).then(|| acl_u32(value)).flatten()),
69+
_ => None,
70+
}
71+
}
72+
5573
fn acl_path_list_attr(block: &a3s_acl::Block, keys: &[&str]) -> Option<Vec<PathBuf>> {
5674
let value = acl_attr(block, keys)?;
5775
match value {
@@ -276,6 +294,37 @@ impl CodeConfig {
276294
model.release_date = Some(release_date);
277295
}
278296
}
297+
"maxTokens" => {
298+
tracing::warn!(
299+
provider = %provider.name,
300+
model = %model.id,
301+
field = "maxTokens",
302+
"Flat ACL model token limit fields are deprecated; use limit = {{ output = ..., context = ... }}"
303+
);
304+
if let Some(output) = acl_u32(value) {
305+
model.limit.output = output;
306+
}
307+
}
308+
"contextTokens" => {
309+
tracing::warn!(
310+
provider = %provider.name,
311+
model = %model.id,
312+
field = "contextTokens",
313+
"Flat ACL model token limit fields are deprecated; use limit = {{ output = ..., context = ... }}"
314+
);
315+
if let Some(context) = acl_u32(value) {
316+
model.limit.context = context;
317+
}
318+
}
319+
"limit" => {
320+
if let Some(output) = acl_object_u32_attr(value, "output") {
321+
model.limit.output = output;
322+
}
323+
if let Some(context) = acl_object_u32_attr(value, "context")
324+
{
325+
model.limit.context = context;
326+
}
327+
}
279328
_ => {}
280329
}
281330
}

core/src/config/tests.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,42 @@ fn test_config_supports_acl_style_provider_labels() {
111111
assert!(config.providers[0].models[0].tool_call);
112112
}
113113

114+
#[test]
115+
fn test_config_parses_acl_model_token_limits() {
116+
let config = CodeConfig::from_acl(
117+
r#"
118+
default_model = "openai/glm-5.1"
119+
120+
providers "openai" {
121+
api_key = "sk-test"
122+
base_url = "http://127.0.0.1:18051/v1"
123+
124+
models "glm-5.1" {
125+
name = "GLM 5.1"
126+
limit = {
127+
output = 4096
128+
context = 32768
129+
}
130+
}
131+
132+
models "flat-alias" {
133+
maxTokens = 8192
134+
contextTokens = 65536
135+
}
136+
}
137+
"#,
138+
)
139+
.unwrap();
140+
141+
let flat = &config.providers[0].models[0].limit;
142+
assert_eq!(flat.output, 4096);
143+
assert_eq!(flat.context, 32768);
144+
145+
let flat_alias = &config.providers[0].models[1].limit;
146+
assert_eq!(flat_alias.output, 8192);
147+
assert_eq!(flat_alias.context, 65536);
148+
}
149+
114150
#[test]
115151
fn test_config_builder() {
116152
let config = CodeConfig::new()

0 commit comments

Comments
 (0)