@miller-tech/uap 1.42.4 → 1.42.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.42.4",
3
+ "version": "1.42.6",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -6,10 +6,10 @@ import sys
6
6
  from pathlib import Path
7
7
 
8
8
  sys.path.insert(0, str(Path(__file__).parent))
9
- from _common import arg_str, emit, parse_cli, run, worktree_root # noqa: E402
9
+ from _common import emit, parse_cli, run, worktree_root # noqa: E402
10
10
 
11
11
  MUTATING_RE = re.compile(
12
- r"\b(kubectl|helm|doctl|aws|gcloud)\b.*?\b(apply|patch|create|edit|delete|install|upgrade|rollout|scale|set)\b",
12
+ r"\b(kubectl|helm|doctl|aws|gcloud)\b[^\n;&|]{0,48}?\b(apply|patch|create|edit|delete|install|upgrade|rollout|scale|set)\b",
13
13
  re.I,
14
14
  )
15
15
  IAC_PATHS = (
@@ -23,9 +23,15 @@ IAC_PATHS = (
23
23
 
24
24
  def main() -> None:
25
25
  op, args = parse_cli()
26
- blob = f"{op} {arg_str(args)}"
27
-
28
- if not MUTATING_RE.search(blob):
26
+ # iac-parity governs live-state MUTATING shell COMMANDS (kubectl apply,
27
+ # helm install, ...). File edits -- including editing IaC manifests, or any
28
+ # content that merely names infra tools -- are never live-state mutations,
29
+ # so only Bash commands are in scope.
30
+ if op.lower() != "bash":
31
+ emit(True, "not a bash command")
32
+ cmd = args.get("command") or args.get("cmd") or ""
33
+
34
+ if not MUTATING_RE.search(cmd):
29
35
  emit(True, "not a mutating IaC-scope command")
30
36
 
31
37
  root = worktree_root() # git status must run against the working tree, not MAIN_ROOT
@@ -37,26 +37,35 @@ logger = logging.getLogger(__name__)
37
37
  # --------------------------------------------------------------------------- #
38
38
 
39
39
 
40
- def _make_opencode_config(api_endpoint: str) -> dict:
40
+ def _make_opencode_config(
41
+ api_endpoint: str, model_ref: str = "llama.cpp/qwen35-a3b-iq4xs"
42
+ ) -> dict:
43
+ # model_ref is the harbor `-m` value, e.g. "llama.cpp/qwen3.6-a3b-iq4xs".
44
+ # Derive the provider + model id so opencode registers EXACTLY the model
45
+ # harbor selects (avoids ProviderModelNotFoundError when the local model
46
+ # changes, e.g. Qwen3.5 -> Qwen3.6).
47
+ provider_id, sep, model_id = model_ref.partition("/")
48
+ if not sep:
49
+ provider_id, model_id = "llama.cpp", model_ref
41
50
  return {
42
51
  "$schema": "https://opencode.ai/config.json",
43
52
  "provider": {
44
- "llama.cpp": {
53
+ provider_id: {
45
54
  "npm": "@ai-sdk/openai-compatible",
46
- "name": "llama-server (local Qwen3.5)",
55
+ "name": "llama-server (local)",
47
56
  "options": {
48
57
  "baseURL": api_endpoint,
49
- "apiKey": "sk-qwen35b",
58
+ "apiKey": "sk-local",
50
59
  },
51
60
  "models": {
52
- "qwen35-a3b-iq4xs": {
53
- "name": "Qwen3.5 35B A3B (IQ4_XS)",
61
+ model_id: {
62
+ "name": model_id,
54
63
  "limit": {"context": 262144, "output": 81920},
55
64
  }
56
65
  },
57
66
  }
58
67
  },
59
- "model": "llama.cpp/qwen35-a3b-iq4xs",
68
+ "model": f"{provider_id}/{model_id}",
60
69
  }
61
70
 
62
71
 
@@ -998,7 +1007,10 @@ class OpenCodeBaseline(BaseInstalledAgent):
998
1007
  if version:
999
1008
  variables["version"] = version
1000
1009
  variables["opencode_config"] = json.dumps(
1001
- _make_opencode_config(self._api_endpoint), indent=2
1010
+ _make_opencode_config(
1011
+ self._api_endpoint, self.model_name or "llama.cpp/qwen35-a3b-iq4xs"
1012
+ ),
1013
+ indent=2,
1002
1014
  )
1003
1015
  variables["api_endpoint"] = self._api_endpoint
1004
1016
  return variables
@@ -1081,11 +1093,20 @@ class OpenCodeUAP(BaseInstalledAgent):
1081
1093
  version = self.version()
1082
1094
  if version:
1083
1095
  variables["version"] = version
1084
- # Layer 1: opencode.json points to proxy at localhost:11435
1085
- # The proxy forwards to the real LLM endpoint and injects tool_choice="required"
1086
- proxy_endpoint = "http://127.0.0.1:11435/v1"
1096
+ # Modern local models (Qwen3.6+) emit native OpenAI tool calls; the
1097
+ # deprecated GBNF-forcing tool-choice proxy (Layer 1) breaks them. Point
1098
+ # opencode at the model endpoint directly by default; set
1099
+ # UAP_BENCH_PROXY=1 to restore the qwen3.5-era proxy path (port 11435).
1100
+ endpoint = (
1101
+ "http://127.0.0.1:11435/v1"
1102
+ if os.environ.get("UAP_BENCH_PROXY") == "1"
1103
+ else self._api_endpoint
1104
+ )
1087
1105
  variables["opencode_config"] = json.dumps(
1088
- _make_opencode_config(proxy_endpoint), indent=2
1106
+ _make_opencode_config(
1107
+ endpoint, self.model_name or "llama.cpp/qwen35-a3b-iq4xs"
1108
+ ),
1109
+ indent=2,
1089
1110
  )
1090
1111
  variables["api_endpoint"] = self._api_endpoint
1091
1112
  # NOTE: CLAUDE.md is now built dynamically per-task in create_run_agent_commands