harnex 0.7.10 → 0.7.11
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +12 -3
- data/guides/01_dispatch.md +14 -0
- data/lib/harnex/commands/run.rb +88 -6
- data/lib/harnex/runtime/session.rb +90 -5
- data/lib/harnex/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 104afb9f09fe59bd24191fde1122294a35ae47069a929022228b4365d653da54
|
|
4
|
+
data.tar.gz: ac8032b88f3c0001718ffc053923000abbba33743e6de4b68459108ca481cbcf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f76c4a9847aebd46cca3bada6c0af0e622bb3840fa53160cb4811c2beac2a007c6a01faadf042ef22f73e55c2ddde5571adc56d774e5b444ece412ad656242e4
|
|
7
|
+
data.tar.gz: 1d9843aa631eb411fa31c772cf5c09b92cc5d5d67ed95583abf041fd250e31343c76215a8949f268563e14609416724fd681bad6bfc5c6b7c270a4f9639e6838
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.7.11] - 2026-07-10 | 11:14 PM | IST
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Dispatch summaries now include top-level additive `agent` and `reliability`
|
|
10
|
+
blocks for every run, and a top-level `queue` block when queue attribution is
|
|
11
|
+
provided. New consumers should prefer these blocks over legacy flat fields for
|
|
12
|
+
queue economics and reliability analytics.
|
|
13
|
+
- `harnex run` now accepts first-class queue/agent telemetry flags:
|
|
14
|
+
`--project-id`, `--queue-id`, `--entry-id`, `--entry-title`, `--phase`,
|
|
15
|
+
`--tier`, `--issue`, `--plan`, `--intent`, `--model`, and `--effort`.
|
|
16
|
+
Explicit flags override same-named `--meta` values and are forwarded through
|
|
17
|
+
tmux re-exec.
|
|
18
|
+
- `harnex run --require-attribution` fails before launching unless required
|
|
19
|
+
queue attribution is present (`project_id`, `phase`, `intent`, and at least
|
|
20
|
+
one work id).
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Dispatch telemetry docs, README, and the packaged dispatch agents-guide now
|
|
25
|
+
document queue attribution, effective agent routing fields, reliability split,
|
|
26
|
+
and a sample queue grouping snippet.
|
|
27
|
+
|
|
5
28
|
## [0.7.10] - 2026-07-10 | 10:57 PM | IST
|
|
6
29
|
|
|
7
30
|
### Added
|
data/README.md
CHANGED
|
@@ -284,9 +284,18 @@ compact `artifact_report`, `validation`, and `artifacts` summary in the dispatch
|
|
|
284
284
|
row. Missing or malformed reports are warning telemetry, not wrapped-process
|
|
285
285
|
crashes.
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
287
|
+
Queue runners can pass first-class attribution without hiding it in prose:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
harnex run pi --project-id harnex --queue-id queue-005 --entry-id SP-4 \
|
|
291
|
+
--phase implement --intent queue-work --require-attribution ...
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Soft budget metadata is copied into summary `meta`; queue/agent/reliability
|
|
295
|
+
metadata is copied into top-level `queue`, `agent`, and `reliability` summary
|
|
296
|
+
blocks. Terminal summary `actual` records timing, exit classification, token
|
|
297
|
+
usage when the adapter can capture it, adapter-reported `cost_usd` when
|
|
298
|
+
reliably available, git deltas,
|
|
290
299
|
task-completion state, operational counters (`stalls`, `force_resumes`,
|
|
291
300
|
`disconnections`, `tool_calls`, `commands_executed`), output/event log paths,
|
|
292
301
|
and rough volume measurements such as `lines_changed`, `output_lines`,
|
data/guides/01_dispatch.md
CHANGED
|
@@ -111,6 +111,20 @@ artifact summaries (`finding`, `review`, `gate`, `blocker`, etc.), evidence,
|
|
|
111
111
|
confidence, and canonical refs. Harnex records missing/malformed sidecars as
|
|
112
112
|
warning telemetry instead of failing the wrapped process.
|
|
113
113
|
|
|
114
|
+
Queue runners should pass first-class attribution so dispatch rows can be grouped
|
|
115
|
+
without path/id heuristics:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
harnex run pi --id pi-i-NN --tmux pi-i-NN \
|
|
119
|
+
--project-id harnex --queue-id queue-005 --entry-id SP-4 \
|
|
120
|
+
--phase implement --intent queue-work --require-attribution \
|
|
121
|
+
--context "Read and execute /tmp/task-impl-NN.md"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`--require-attribution` fails before launch unless `project_id`, `phase`,
|
|
125
|
+
`intent`, and at least one work id (`queue_id`, `entry_id`, `issue`, or `plan`)
|
|
126
|
+
are present.
|
|
127
|
+
|
|
114
128
|
Pi runs use structured RPC (`pi --mode rpc`). Pass Pi child flags after `--`
|
|
115
129
|
(e.g. `harnex run pi --context "..." -- --model anthropic/claude-sonnet-4-5 --thinking high`).
|
|
116
130
|
|
data/lib/harnex/commands/run.rb
CHANGED
|
@@ -5,15 +5,33 @@ require "shellwords"
|
|
|
5
5
|
module Harnex
|
|
6
6
|
class Runner
|
|
7
7
|
DEFAULT_TIMEOUT = 5.0
|
|
8
|
+
TELEMETRY_FLAGS = {
|
|
9
|
+
"--project-id" => "project_id",
|
|
10
|
+
"--queue-id" => "queue_id",
|
|
11
|
+
"--entry-id" => "entry_id",
|
|
12
|
+
"--entry-title" => "entry_title",
|
|
13
|
+
"--phase" => "phase",
|
|
14
|
+
"--tier" => "tier",
|
|
15
|
+
"--issue" => "issue",
|
|
16
|
+
"--plan" => "plan",
|
|
17
|
+
"--intent" => "intent",
|
|
18
|
+
"--model" => "model",
|
|
19
|
+
"--effort" => "effort"
|
|
20
|
+
}.freeze
|
|
21
|
+
TELEMETRY_KEYS_TO_FLAGS = TELEMETRY_FLAGS.invert.freeze
|
|
22
|
+
TELEMETRY_EQUALS_PREFIXES = TELEMETRY_FLAGS.keys.map { |flag| "#{flag}=" }.freeze
|
|
23
|
+
|
|
8
24
|
KNOWN_FLAGS = %w[
|
|
9
25
|
--id --description --detach --tmux --host --port --watch --watch-file
|
|
10
26
|
--stall-after --max-resumes --preset --context --meta --summary-out
|
|
11
|
-
--artifact-report --validation-report --cwd --root --timeout --inbox-ttl
|
|
12
|
-
|
|
27
|
+
--artifact-report --validation-report --cwd --root --timeout --inbox-ttl
|
|
28
|
+
--require-attribution --auto-stop --fast --legacy-pty --help
|
|
29
|
+
].concat(TELEMETRY_FLAGS.keys).freeze
|
|
13
30
|
VALUE_FLAGS = %w[
|
|
14
31
|
--id --description --host --port --watch --watch-file --stall-after
|
|
15
|
-
--max-resumes --preset --context --meta --summary-out --artifact-report
|
|
16
|
-
|
|
32
|
+
--max-resumes --preset --context --meta --summary-out --artifact-report
|
|
33
|
+
--validation-report --cwd --root --timeout --inbox-ttl
|
|
34
|
+
].concat(TELEMETRY_FLAGS.keys).freeze
|
|
17
35
|
|
|
18
36
|
def self.usage(program_name = "harnex run")
|
|
19
37
|
<<~TEXT
|
|
@@ -41,6 +59,19 @@ module Harnex
|
|
|
41
59
|
Worker-written harnex.artifact_report.v1 JSON sidecar to ingest at exit
|
|
42
60
|
--validation-report PATH
|
|
43
61
|
Alias for --artifact-report; also exposed as HARNEX_VALIDATION_REPORT_PATH
|
|
62
|
+
--project-id ID Queue telemetry project id (first-class flags override --meta)
|
|
63
|
+
--queue-id ID Queue telemetry queue id
|
|
64
|
+
--entry-id ID Queue telemetry entry id
|
|
65
|
+
--entry-title TEXT Queue telemetry entry title
|
|
66
|
+
--phase TEXT Queue/work phase telemetry
|
|
67
|
+
--tier TEXT Queue/work tier telemetry
|
|
68
|
+
--issue ID Queue/work issue telemetry
|
|
69
|
+
--plan ID Queue/work plan telemetry
|
|
70
|
+
--intent TEXT Queue/work intent telemetry
|
|
71
|
+
--model NAME Requested model metadata (also used for structured dispatch)
|
|
72
|
+
--effort LEVEL Requested reasoning effort metadata (structured dispatch)
|
|
73
|
+
--require-attribution
|
|
74
|
+
Fail before launch unless project/phase/intent and one work id are present
|
|
44
75
|
--cwd DIR Run the wrapped agent from DIR and use DIR as the session root
|
|
45
76
|
--root DIR Override harnex session/root attribution without changing child cwd
|
|
46
77
|
--timeout SECS Max seconds to wait for detached registration (default: #{DEFAULT_TIMEOUT})
|
|
@@ -66,6 +97,7 @@ module Harnex
|
|
|
66
97
|
#{program_name} pi --id pi-i-42 --watch --preset impl --context "Read /tmp/task-impl-42.md"
|
|
67
98
|
#{program_name} codex --cwd /tmp/public-bundle --id eval-001 --context "Read README.md and write OUTPUT.md" --auto-stop
|
|
68
99
|
#{program_name} pi --id pi-i-52 --artifact-report .harnex/reports/pi-i-52.json --context "Write proof to $HARNEX_ARTIFACT_REPORT_PATH" --auto-stop
|
|
100
|
+
#{program_name} pi --project-id harnex --queue-id queue-005 --entry-id SP-4 --phase implement --intent queue-work --require-attribution --context "Implement SP-4"
|
|
69
101
|
#{program_name} claude --id cl-r-42 --tmux cl-r-42 --description "Review task 42"
|
|
70
102
|
|
|
71
103
|
Gotchas:
|
|
@@ -95,6 +127,8 @@ module Harnex
|
|
|
95
127
|
watch: nil,
|
|
96
128
|
context: nil,
|
|
97
129
|
meta: nil,
|
|
130
|
+
telemetry: {},
|
|
131
|
+
require_attribution: false,
|
|
98
132
|
summary_out: nil,
|
|
99
133
|
artifact_report: nil,
|
|
100
134
|
cwd: nil,
|
|
@@ -120,6 +154,8 @@ module Harnex
|
|
|
120
154
|
|
|
121
155
|
raise OptionParser::MissingArgument, "cli" if cli_name.nil?
|
|
122
156
|
validate_auto_stop_context!
|
|
157
|
+
apply_telemetry_options!
|
|
158
|
+
validate_required_attribution!
|
|
123
159
|
|
|
124
160
|
repo_root = resolve_run_root(cli_name, child_args)
|
|
125
161
|
@options[:summary_out] = resolve_summary_out(repo_root)
|
|
@@ -184,6 +220,11 @@ module Harnex
|
|
|
184
220
|
tmux_cmd += ["--context", @options[:context]] if @options[:context]
|
|
185
221
|
tmux_cmd << "--auto-stop" if @options[:auto_stop]
|
|
186
222
|
tmux_cmd += ["--meta", JSON.generate(@options[:meta])] if @options[:meta]
|
|
223
|
+
@options[:telemetry].each do |key, value|
|
|
224
|
+
flag = TELEMETRY_KEYS_TO_FLAGS[key]
|
|
225
|
+
tmux_cmd += [flag, value] if flag && value
|
|
226
|
+
end
|
|
227
|
+
tmux_cmd << "--require-attribution" if @options[:require_attribution]
|
|
187
228
|
tmux_cmd += ["--summary-out", @options[:summary_out]] if @options[:summary_out]
|
|
188
229
|
tmux_cmd += ["--artifact-report", @options[:artifact_report]] if @options[:artifact_report]
|
|
189
230
|
tmux_cmd += ["--cwd", @options[:cwd]] if @options[:cwd]
|
|
@@ -465,6 +506,8 @@ module Harnex
|
|
|
465
506
|
@options[:context] = required_option_value("--context", Regexp.last_match(1))
|
|
466
507
|
when "--auto-stop"
|
|
467
508
|
@options[:auto_stop] = true
|
|
509
|
+
when "--require-attribution"
|
|
510
|
+
@options[:require_attribution] = true
|
|
468
511
|
when "--fast"
|
|
469
512
|
@options[:fast] = true
|
|
470
513
|
when "--meta"
|
|
@@ -472,6 +515,12 @@ module Harnex
|
|
|
472
515
|
@options[:meta] = parse_meta(required_option_value(arg, argv[index]))
|
|
473
516
|
when /\A--meta=(.+)\z/
|
|
474
517
|
@options[:meta] = parse_meta(required_option_value("--meta", Regexp.last_match(1)))
|
|
518
|
+
when *TELEMETRY_FLAGS.keys
|
|
519
|
+
index += 1
|
|
520
|
+
@options[:telemetry][TELEMETRY_FLAGS.fetch(arg)] = required_option_value(arg, argv[index])
|
|
521
|
+
when telemetry_equals_regex
|
|
522
|
+
flag = "--#{Regexp.last_match(1)}"
|
|
523
|
+
@options[:telemetry][TELEMETRY_FLAGS.fetch(flag)] = required_option_value(flag, Regexp.last_match(2))
|
|
475
524
|
when "--summary-out"
|
|
476
525
|
index += 1
|
|
477
526
|
@options[:summary_out] = required_option_value(arg, argv[index])
|
|
@@ -520,6 +569,10 @@ module Harnex
|
|
|
520
569
|
[cli_name, forwarded]
|
|
521
570
|
end
|
|
522
571
|
|
|
572
|
+
def telemetry_equals_regex
|
|
573
|
+
@telemetry_equals_regex ||= /\A--(#{TELEMETRY_FLAGS.keys.map { |flag| Regexp.escape(flag.delete_prefix("--")) }.join("|")})=(.+)\z/
|
|
574
|
+
end
|
|
575
|
+
|
|
523
576
|
def unknown_long_flag?(arg)
|
|
524
577
|
arg.start_with?("--")
|
|
525
578
|
end
|
|
@@ -556,7 +609,7 @@ module Harnex
|
|
|
556
609
|
case arg
|
|
557
610
|
when "--"
|
|
558
611
|
return false
|
|
559
|
-
when "-h", "--help", "--detach", "--tmux", "--auto-stop", "--fast", "--legacy-pty"
|
|
612
|
+
when "-h", "--help", "--detach", "--tmux", "--auto-stop", "--require-attribution", "--fast", "--legacy-pty"
|
|
560
613
|
nil
|
|
561
614
|
when /\A--tmux=/
|
|
562
615
|
nil
|
|
@@ -564,6 +617,8 @@ module Harnex
|
|
|
564
617
|
index += 1
|
|
565
618
|
when /\A--(?:id|description|host|port|watch|watch-file|stall-after|max-resumes|context|meta|summary-out|artifact-report|validation-report|cwd|root|timeout|inbox-ttl)=/
|
|
566
619
|
nil
|
|
620
|
+
when telemetry_equals_regex
|
|
621
|
+
nil
|
|
567
622
|
when /\A--preset=/
|
|
568
623
|
nil
|
|
569
624
|
else
|
|
@@ -581,7 +636,8 @@ module Harnex
|
|
|
581
636
|
arg.start_with?(
|
|
582
637
|
"--id=", "--description=", "--tmux=", "--host=", "--port=", "--watch=", "--watch-file=",
|
|
583
638
|
"--stall-after=", "--max-resumes=", "--preset=", "--context=", "--meta=", "--summary-out=",
|
|
584
|
-
"--artifact-report=", "--validation-report=", "--cwd=", "--root=", "--timeout=", "--inbox-ttl="
|
|
639
|
+
"--artifact-report=", "--validation-report=", "--cwd=", "--root=", "--timeout=", "--inbox-ttl=",
|
|
640
|
+
*TELEMETRY_EQUALS_PREFIXES
|
|
585
641
|
)
|
|
586
642
|
end
|
|
587
643
|
|
|
@@ -610,6 +666,32 @@ module Harnex
|
|
|
610
666
|
raise OptionParser::InvalidOption, "harnex run: --auto-stop requires --context"
|
|
611
667
|
end
|
|
612
668
|
|
|
669
|
+
def apply_telemetry_options!
|
|
670
|
+
explicit = @options[:telemetry]
|
|
671
|
+
return if explicit.empty? && @options[:meta].is_a?(Hash)
|
|
672
|
+
return if explicit.empty?
|
|
673
|
+
|
|
674
|
+
@options[:meta] = (@options[:meta].is_a?(Hash) ? @options[:meta].dup : {}).merge(explicit)
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
def validate_required_attribution!
|
|
678
|
+
return unless @options[:require_attribution]
|
|
679
|
+
|
|
680
|
+
metadata = @options[:meta].is_a?(Hash) ? @options[:meta] : {}
|
|
681
|
+
missing = %w[project_id phase intent].select { |key| blank_value?(metadata[key]) }
|
|
682
|
+
unless %w[queue_id entry_id issue plan].any? { |key| !blank_value?(metadata[key]) }
|
|
683
|
+
missing << "one of queue_id/entry_id/issue/plan"
|
|
684
|
+
end
|
|
685
|
+
return if missing.empty?
|
|
686
|
+
|
|
687
|
+
raise OptionParser::InvalidOption,
|
|
688
|
+
"harnex run: --require-attribution missing #{missing.join(', ')}"
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def blank_value?(value)
|
|
692
|
+
value.nil? || value.to_s.strip.empty?
|
|
693
|
+
end
|
|
694
|
+
|
|
613
695
|
def apply_codex_service_tier(cli_name, child_args)
|
|
614
696
|
return child_args unless cli_name.to_s == "codex"
|
|
615
697
|
return child_args if child_service_tier_config?(child_args)
|
|
@@ -16,6 +16,11 @@ module Harnex
|
|
|
16
16
|
agent_session_id cost_usd
|
|
17
17
|
].freeze
|
|
18
18
|
BUDGET_META_FIELDS = %w[read_budget_lines output_ceiling_lines].freeze
|
|
19
|
+
QUEUE_FIELDS = %w[project_id queue_id entry_id entry_title issue plan phase tier intent].freeze
|
|
20
|
+
AGENT_FIELDS = %w[cli provider model_requested model_effective reasoning_effort service_tier adapter_transport].freeze
|
|
21
|
+
RELIABILITY_FIELDS = %w[
|
|
22
|
+
adapter_close real_disconnections stream_interruptions stalls force_resumes compactions recovered
|
|
23
|
+
].freeze
|
|
19
24
|
SUCCESSFUL_TURN_STATUSES = %w[completed success succeeded].freeze
|
|
20
25
|
class EventCounters
|
|
21
26
|
def initialize
|
|
@@ -1168,8 +1173,12 @@ module Harnex
|
|
|
1168
1173
|
record = {
|
|
1169
1174
|
meta: build_summary_meta,
|
|
1170
1175
|
predicted: summary_predicted_payload,
|
|
1171
|
-
actual: build_summary_actual
|
|
1176
|
+
actual: build_summary_actual,
|
|
1177
|
+
agent: build_summary_agent,
|
|
1178
|
+
reliability: build_summary_reliability
|
|
1172
1179
|
}
|
|
1180
|
+
queue = build_summary_queue
|
|
1181
|
+
record[:queue] = queue if queue
|
|
1173
1182
|
record.merge!(artifact_report_summary) if artifact_report_path
|
|
1174
1183
|
record
|
|
1175
1184
|
end
|
|
@@ -1207,12 +1216,42 @@ module Harnex
|
|
|
1207
1216
|
}.merge(summary_budget_meta)
|
|
1208
1217
|
end
|
|
1209
1218
|
|
|
1219
|
+
def build_summary_queue
|
|
1220
|
+
queue = QUEUE_FIELDS.to_h { |field| [field, summary_string(meta_hash[field])] }
|
|
1221
|
+
return nil if queue.values.all?(&:nil?)
|
|
1222
|
+
|
|
1223
|
+
queue
|
|
1224
|
+
end
|
|
1225
|
+
|
|
1226
|
+
def build_summary_agent
|
|
1227
|
+
{
|
|
1228
|
+
"cli" => adapter.key,
|
|
1229
|
+
"provider" => summary_agent_provider,
|
|
1230
|
+
"model_requested" => summary_string(meta_hash["model"]),
|
|
1231
|
+
"model_effective" => summary_string(summary_model),
|
|
1232
|
+
"reasoning_effort" => summary_string(meta_hash["effort"]),
|
|
1233
|
+
"service_tier" => summary_service_tier,
|
|
1234
|
+
"adapter_transport" => adapter.transport.to_s
|
|
1235
|
+
}
|
|
1236
|
+
end
|
|
1237
|
+
|
|
1238
|
+
def build_summary_reliability
|
|
1239
|
+
counters = summary_event_counters
|
|
1240
|
+
real_disconnections = counters[:disconnections].to_i
|
|
1241
|
+
{
|
|
1242
|
+
"adapter_close" => summary_adapter_close(real_disconnections),
|
|
1243
|
+
"real_disconnections" => real_disconnections,
|
|
1244
|
+
"stream_interruptions" => real_disconnections,
|
|
1245
|
+
"stalls" => counters[:stalls].to_i,
|
|
1246
|
+
"force_resumes" => counters[:force_resumes].to_i,
|
|
1247
|
+
"compactions" => counters[:compactions].to_i,
|
|
1248
|
+
"recovered" => false
|
|
1249
|
+
}
|
|
1250
|
+
end
|
|
1251
|
+
|
|
1210
1252
|
def build_summary_actual
|
|
1211
|
-
counters =
|
|
1253
|
+
counters = summary_event_counters
|
|
1212
1254
|
output_measurements = summary_output_measurements
|
|
1213
|
-
if %w[disconnected boot_failure].include?(@exit_reason)
|
|
1214
|
-
counters[:disconnections] = [counters[:disconnections], 1].max
|
|
1215
|
-
end
|
|
1216
1255
|
|
|
1217
1256
|
actual = {
|
|
1218
1257
|
model: summary_model,
|
|
@@ -1298,6 +1337,52 @@ module Harnex
|
|
|
1298
1337
|
(adapter.current_model if adapter.respond_to?(:current_model))
|
|
1299
1338
|
end
|
|
1300
1339
|
|
|
1340
|
+
def summary_service_tier
|
|
1341
|
+
summary_string(meta_hash["service_tier"]) || service_tier_from_command
|
|
1342
|
+
end
|
|
1343
|
+
|
|
1344
|
+
def service_tier_from_command
|
|
1345
|
+
command.each_with_index do |arg, index|
|
|
1346
|
+
text = arg.to_s
|
|
1347
|
+
if text == "-c" || text == "--config"
|
|
1348
|
+
parsed = parse_service_tier_config(command[index + 1])
|
|
1349
|
+
return parsed if parsed
|
|
1350
|
+
end
|
|
1351
|
+
parsed = parse_service_tier_config(text)
|
|
1352
|
+
return parsed if parsed
|
|
1353
|
+
end
|
|
1354
|
+
nil
|
|
1355
|
+
end
|
|
1356
|
+
|
|
1357
|
+
def parse_service_tier_config(value)
|
|
1358
|
+
text = value.to_s
|
|
1359
|
+
match = text.match(/(?:\A|=)service_tier=\\?"?([^"\s]+)\\?"?/)
|
|
1360
|
+
return nil unless match
|
|
1361
|
+
|
|
1362
|
+
summary_string(match[1])
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
def summary_event_counters
|
|
1366
|
+
counters = @event_counters.snapshot
|
|
1367
|
+
if %w[disconnected boot_failure].include?(@exit_reason)
|
|
1368
|
+
counters[:disconnections] = [counters[:disconnections], 1].max
|
|
1369
|
+
end
|
|
1370
|
+
counters
|
|
1371
|
+
end
|
|
1372
|
+
|
|
1373
|
+
def summary_adapter_close(real_disconnections)
|
|
1374
|
+
return "interrupted" if @exit_code == 124 || @term_signal
|
|
1375
|
+
return "lost" if %w[disconnected boot_failure].include?(@exit_reason) || real_disconnections.to_i.positive?
|
|
1376
|
+
return "normal" if %w[success failure].include?(@exit_reason)
|
|
1377
|
+
|
|
1378
|
+
"unknown"
|
|
1379
|
+
end
|
|
1380
|
+
|
|
1381
|
+
def summary_string(value)
|
|
1382
|
+
text = value.to_s
|
|
1383
|
+
text.empty? ? nil : text
|
|
1384
|
+
end
|
|
1385
|
+
|
|
1301
1386
|
def summary_tool_calls(counters)
|
|
1302
1387
|
@usage_summary[:tool_calls] || counters[:tool_calls]
|
|
1303
1388
|
end
|
data/lib/harnex/version.rb
CHANGED