@data-matters.io/agent-harness 0.1.9 → 0.1.10
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 +1 -1
- package/templates/.harness/lib.sh +32 -1
- package/templates/.harness/quota.sh +23 -0
package/package.json
CHANGED
|
@@ -47,6 +47,15 @@ harness_session_error_text() {
|
|
|
47
47
|
: raw);' "$1" 2>/dev/null
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
# harness_session_api_error <session.json>: the session's api_error field, the
|
|
51
|
+
# structured value the runtime sets when the API refused (usage_limit_reached).
|
|
52
|
+
# Empty when the session carries none.
|
|
53
|
+
harness_session_api_error() {
|
|
54
|
+
node -e "$harness_session_js"'
|
|
55
|
+
const d = session(process.argv[1]);
|
|
56
|
+
process.stdout.write(typeof d.api_error === "string" ? d.api_error : "");' "$1" 2>/dev/null
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
# harness_api_refused <session.json>: the session ended on an error that says
|
|
51
60
|
# the API cannot serve it: no credit, a quota, a spend or usage limit, billing,
|
|
52
61
|
# an invalid key, or the gateway itself failing (503 or another 5xx, a
|
|
@@ -156,8 +165,30 @@ harness_claude_flags() {
|
|
|
156
165
|
# session limit") and sets api_error to usage_limit_reached, so both are matched;
|
|
157
166
|
# the gateway's Portuguese quota message is matched too, and its transient 429
|
|
158
167
|
# is not (quota.sh, ADR 0025 section 8).
|
|
168
|
+
#
|
|
169
|
+
# Only the session's own FAILURE is read: the api_error field, and the error
|
|
170
|
+
# text of a session that ended with is_error (harness_session_error_text).
|
|
171
|
+
# The answer of a session that ended well is never a usage error by what it
|
|
172
|
+
# says: a task that explains an old quota event ("cota semanal") is a task
|
|
173
|
+
# about a quota, not a quota. The one exception is the gateway's quota notice,
|
|
174
|
+
# which arrives unmarked, in the body of a 200: there the whole answer IS the
|
|
175
|
+
# notice, so a short answer that carries a quota marker still is a usage error
|
|
176
|
+
# (harness_quota_notice_unmarked).
|
|
159
177
|
harness_usage_error() {
|
|
160
|
-
|
|
178
|
+
local text reply
|
|
179
|
+
text="$(harness_session_error_text "$1")"
|
|
180
|
+
if [[ -n "$text" ]]; then
|
|
181
|
+
# The session failed: its error text (its result and its api_error) is the
|
|
182
|
+
# message the rule is about.
|
|
183
|
+
if harness_quota_exhausted "$text"; then return 0; fi
|
|
184
|
+
return 1
|
|
185
|
+
fi
|
|
186
|
+
# The session ended well: its answer is not a usage error by what it says.
|
|
187
|
+
# The api_error field still counts (usage_limit_reached), and the gateway's
|
|
188
|
+
# unmarked notice is the one answer that IS the notice.
|
|
189
|
+
if harness_quota_exhausted "$(harness_session_api_error "$1")"; then return 0; fi
|
|
190
|
+
reply="$(harness_session_reply "$1")" || return 1
|
|
191
|
+
harness_quota_notice_unmarked "$reply"
|
|
161
192
|
}
|
|
162
193
|
|
|
163
194
|
# harness_level_descend <level>: the level one below, for the fallback after a
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
# a quota marker and no transient marker. A 429 alone is not enough in
|
|
12
12
|
# either direction: both gateway messages carry the same structured
|
|
13
13
|
# fields, so only the text tells them apart.
|
|
14
|
+
# (c) is a session that ENDED WELL the gateway's quota notice?
|
|
15
|
+
# harness_quota_notice_unmarked <text>
|
|
16
|
+
# the gateway sometimes answers 200 with the quota notice in the body,
|
|
17
|
+
# without marking it as an error: there the whole answer is the notice.
|
|
14
18
|
# A transient 429 (harness_quota_transient) is neither: it may be retried and
|
|
15
19
|
# changes nothing.
|
|
16
20
|
#
|
|
@@ -52,6 +56,25 @@ harness_quota_exhausted() {
|
|
|
52
56
|
grep -qE -- "$harness_quota_markers" <<<"$t" && ! grep -qE -- "$harness_quota_transient_markers" <<<"$t"
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
# The longest text that can be the gateway's quota notice. The notice arrives
|
|
60
|
+
# in the body of a 200 response, without being marked as an error (the rule of
|
|
61
|
+
# the watchdog, vps-bootstrap, 2026-11-11): there the whole answer IS the
|
|
62
|
+
# notice. A long answer that talks about a quota is a task about a quota, not a
|
|
63
|
+
# quota.
|
|
64
|
+
harness_quota_notice_max_len=400
|
|
65
|
+
|
|
66
|
+
# harness_quota_notice_unmarked <text>: the text is the gateway's quota notice
|
|
67
|
+
# that arrived unmarked: a SHORT message (at most harness_quota_notice_max_len
|
|
68
|
+
# characters) that carries a quota marker. The markers are the ones above (one
|
|
69
|
+
# list, ADR 0025 section 8): this rule only says how much of the answer may
|
|
70
|
+
# be the notice.
|
|
71
|
+
harness_quota_notice_unmarked() {
|
|
72
|
+
local t="$1" len
|
|
73
|
+
len=${#t}
|
|
74
|
+
(( len <= harness_quota_notice_max_len )) || return 1
|
|
75
|
+
harness_quota_exhausted "$t"
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
# harness_api_unreachable <text>: the gateway failed (503 or another 5xx, a
|
|
56
79
|
# connection failure, a timeout): the API does not answer, whatever the quota.
|
|
57
80
|
harness_api_unreachable() {
|