@miller-tech/uap 1.94.0 → 1.95.0
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/dist/.tsbuildinfo +1 -1
- package/dist/benchmarks/benchmark.d.ts +4 -4
- package/dist/benchmarks/paired/types.d.ts +2 -2
- package/dist/bin/cli.js +12 -2
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +5 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +232 -12
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/task.d.ts +1 -1
- package/dist/cli/task.d.ts.map +1 -1
- package/dist/cli/task.js +33 -0
- package/dist/cli/task.js.map +1 -1
- package/dist/coordination/reactor.d.ts.map +1 -1
- package/dist/coordination/reactor.js +14 -0
- package/dist/coordination/reactor.js.map +1 -1
- package/dist/delivery/applier.d.ts.map +1 -1
- package/dist/delivery/applier.js +3 -0
- package/dist/delivery/applier.js.map +1 -1
- package/dist/delivery/auto-mine.d.ts +27 -0
- package/dist/delivery/auto-mine.d.ts.map +1 -0
- package/dist/delivery/auto-mine.js +73 -0
- package/dist/delivery/auto-mine.js.map +1 -0
- package/dist/delivery/auto-optimizer.d.ts +6 -2
- package/dist/delivery/auto-optimizer.d.ts.map +1 -1
- package/dist/delivery/auto-optimizer.js +12 -5
- package/dist/delivery/auto-optimizer.js.map +1 -1
- package/dist/delivery/convergence-loop.d.ts +45 -0
- package/dist/delivery/convergence-loop.d.ts.map +1 -1
- package/dist/delivery/convergence-loop.js +81 -2
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/decompose.d.ts +45 -0
- package/dist/delivery/decompose.d.ts.map +1 -0
- package/dist/delivery/decompose.js +122 -0
- package/dist/delivery/decompose.js.map +1 -0
- package/dist/delivery/escalation.d.ts +2 -0
- package/dist/delivery/escalation.d.ts.map +1 -1
- package/dist/delivery/escalation.js +5 -0
- package/dist/delivery/escalation.js.map +1 -1
- package/dist/delivery/index.d.ts +5 -1
- package/dist/delivery/index.d.ts.map +1 -1
- package/dist/delivery/index.js +4 -0
- package/dist/delivery/index.js.map +1 -1
- package/dist/delivery/run-state.d.ts +44 -0
- package/dist/delivery/run-state.d.ts.map +1 -0
- package/dist/delivery/run-state.js +137 -0
- package/dist/delivery/run-state.js.map +1 -0
- package/dist/delivery/task-sync.d.ts +47 -0
- package/dist/delivery/task-sync.d.ts.map +1 -0
- package/dist/delivery/task-sync.js +148 -0
- package/dist/delivery/task-sync.js.map +1 -0
- package/dist/mcp-router/tools/deliver.d.ts +48 -0
- package/dist/mcp-router/tools/deliver.d.ts.map +1 -1
- package/dist/mcp-router/tools/deliver.js +64 -4
- package/dist/mcp-router/tools/deliver.js.map +1 -1
- package/dist/observability/halo-exporter.d.ts +4 -3
- package/dist/observability/halo-exporter.d.ts.map +1 -1
- package/dist/observability/halo-exporter.js +9 -5
- package/dist/observability/halo-exporter.js.map +1 -1
- package/dist/state/manifest.d.ts +34 -0
- package/dist/state/manifest.d.ts.map +1 -0
- package/dist/state/manifest.js +152 -0
- package/dist/state/manifest.js.map +1 -0
- package/dist/state/reactor-inject.d.ts +14 -0
- package/dist/state/reactor-inject.d.ts.map +1 -0
- package/dist/state/reactor-inject.js +25 -0
- package/dist/state/reactor-inject.js.map +1 -0
- package/dist/tasks/service.d.ts +7 -0
- package/dist/tasks/service.d.ts.map +1 -1
- package/dist/tasks/service.js +23 -0
- package/dist/tasks/service.js.map +1 -1
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/delivery_enforcement.py +1 -1
- package/templates/hooks/deliver_autoroute.py +60 -10
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
|
@@ -12,12 +12,14 @@ the block carries route == "deliver", the helper:
|
|
|
12
12
|
3. Prints the (possibly annotated) block message on stdout for the hook to
|
|
13
13
|
surface to the agent.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
Autoroute is ON by default (UAP_DELIVER_AUTOROUTE=0 to disable): the blocked
|
|
16
|
+
intent is logged AND routed. The hook still blocks (exit 2); this only enriches
|
|
17
|
+
the block message and kicks off the sanctioned path in the background.
|
|
17
18
|
"""
|
|
18
19
|
import argparse
|
|
19
20
|
import json
|
|
20
21
|
import os
|
|
22
|
+
import re
|
|
21
23
|
import sys
|
|
22
24
|
import time
|
|
23
25
|
from pathlib import Path
|
|
@@ -28,8 +30,11 @@ UAP_DIR = ".uap"
|
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def _autoroute_enabled() -> bool:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
# Default ON: a blocked source edit auto-routes into `uap deliver` in the
|
|
34
|
+
# background instead of dead-ending the agent. Opt out with
|
|
35
|
+
# UAP_DELIVER_AUTOROUTE=0/off/false/no.
|
|
36
|
+
v = os.environ.get("UAP_DELIVER_AUTOROUTE", "on").lower()
|
|
37
|
+
return v not in {"0", "off", "false", "no"}
|
|
33
38
|
|
|
34
39
|
|
|
35
40
|
def decide(out: dict, tool: str, args: dict, autoroute_on: bool, seen_files: set) -> dict:
|
|
@@ -37,6 +42,11 @@ def decide(out: dict, tool: str, args: dict, autoroute_on: bool, seen_files: set
|
|
|
37
42
|
reason = out.get("reason", "")
|
|
38
43
|
route = out.get("route")
|
|
39
44
|
hint = out.get("deliverHint") or ""
|
|
45
|
+
# Older enforcers emitted a full command line ('uap deliver "..."'); the
|
|
46
|
+
# hint is the INSTRUCTION — unwrap so the mission text isn't a command.
|
|
47
|
+
m = re.fullmatch(r'uap deliver "(.+)"', hint.strip())
|
|
48
|
+
if m:
|
|
49
|
+
hint = m.group(1)
|
|
40
50
|
file_path = args.get("file_path") or args.get("path") or args.get("target") or ""
|
|
41
51
|
|
|
42
52
|
if route != "deliver":
|
|
@@ -49,7 +59,7 @@ def decide(out: dict, tool: str, args: dict, autoroute_on: bool, seen_files: set
|
|
|
49
59
|
if spawn:
|
|
50
60
|
message = reason + " [auto-routed to `uap deliver` — running in the background]"
|
|
51
61
|
elif autoroute_on and file_path in seen_files:
|
|
52
|
-
message = reason + " [already auto-routed to `uap deliver` this
|
|
62
|
+
message = reason + " [already auto-routed to `uap deliver` for this file — see .uap/autoroute.log / pending-deliver.jsonl]"
|
|
53
63
|
return {"message": message, "route": route, "spawn": spawn,
|
|
54
64
|
"file_path": file_path, "hint": hint, "intent": intent}
|
|
55
65
|
|
|
@@ -65,16 +75,56 @@ def _load_seen(root: Path) -> set:
|
|
|
65
75
|
return set()
|
|
66
76
|
|
|
67
77
|
|
|
78
|
+
LOCK_FILE = "autoroute.lock"
|
|
79
|
+
LOG_FILE = "autoroute.log"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _pid_alive(pid: int) -> bool:
|
|
83
|
+
try:
|
|
84
|
+
os.kill(pid, 0)
|
|
85
|
+
return True
|
|
86
|
+
except Exception:
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _acquire_slot(root: Path) -> bool:
|
|
91
|
+
"""One in-flight autoroute deliver per repo: a lockfile holding the child
|
|
92
|
+
pid. Stale locks (dead pid) are reclaimed. Best-effort; failure = no slot."""
|
|
93
|
+
lock = root / UAP_DIR / LOCK_FILE
|
|
94
|
+
try:
|
|
95
|
+
if lock.exists():
|
|
96
|
+
pid = int(lock.read_text().strip() or "0")
|
|
97
|
+
if pid and _pid_alive(pid):
|
|
98
|
+
return False
|
|
99
|
+
return True
|
|
100
|
+
except Exception:
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
|
|
68
104
|
def _spawn_deliver(root: Path, hint: str) -> None:
|
|
69
|
-
"""Spawn `uap deliver "<hint>"` fully detached. Best-effort; never
|
|
105
|
+
"""Spawn `uap deliver -- "<hint>"` fully detached. Best-effort; never
|
|
106
|
+
raises. The hint is passed after `--` (a pure operand — no flag smuggling),
|
|
107
|
+
bounded turn budget, output logged to .uap/autoroute.log for visibility."""
|
|
70
108
|
import subprocess
|
|
109
|
+
if hint.startswith("-"):
|
|
110
|
+
return # never let a hint be parsed as a flag
|
|
111
|
+
if not _acquire_slot(root):
|
|
112
|
+
return # another autoroute mission is already converging in this repo
|
|
113
|
+
try:
|
|
114
|
+
log = (root / UAP_DIR / LOG_FILE).open("a")
|
|
115
|
+
except Exception:
|
|
116
|
+
log = subprocess.DEVNULL
|
|
71
117
|
try:
|
|
72
|
-
subprocess.Popen(
|
|
73
|
-
["uap", "deliver", hint],
|
|
118
|
+
proc = subprocess.Popen(
|
|
119
|
+
["uap", "deliver", "--max-turns", "5", "--ceiling", "10", "--", hint],
|
|
74
120
|
cwd=str(root),
|
|
75
|
-
stdout=
|
|
121
|
+
stdout=log, stderr=log, stdin=subprocess.DEVNULL,
|
|
76
122
|
start_new_session=True,
|
|
77
123
|
)
|
|
124
|
+
try:
|
|
125
|
+
(root / UAP_DIR / LOCK_FILE).write_text(str(proc.pid))
|
|
126
|
+
except Exception:
|
|
127
|
+
pass
|
|
78
128
|
except Exception:
|
|
79
129
|
pass
|
|
80
130
|
|
|
@@ -111,7 +161,7 @@ def main() -> None:
|
|
|
111
161
|
if d["spawn"]:
|
|
112
162
|
try:
|
|
113
163
|
with _seen_path(root).open("a") as f:
|
|
114
|
-
f.write(d["file_path"] + "\n")
|
|
164
|
+
f.write(d["file_path"].replace("\n", " ").replace("\r", " ") + "\n")
|
|
115
165
|
except Exception:
|
|
116
166
|
pass
|
|
117
167
|
_spawn_deliver(root, d["hint"])
|