@rubytech/create-realagent-code 0.1.510 → 0.1.512
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/payload/platform/package.json +3 -0
- package/payload/platform/plugins/admin/skills/deck-pages/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/skill-builder/SKILL.md +1 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +10 -0
- package/payload/platform/plugins/business-assistant/skills/e-sign/SKILL.md +15 -34
- package/payload/platform/plugins/business-assistant/skills/e-sign/stamp.mjs +269 -0
- package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/profile.md +5 -5
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -2
- package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -1
- package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +1 -1
- package/payload/platform/scripts/check-no-esm-require.mjs +6 -0
- package/payload/platform/scripts/logs-read.sh +117 -36
- package/payload/platform/scripts/logs-read.test.sh +234 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +13 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -3
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +17 -11
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/brand-design/SKILL.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/copy.md +2 -2
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/images.md +2 -2
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/index-landing.md +2 -2
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/index.html +3 -3
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/placeholders.md +16 -16
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/registers.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/seller-brief.md +3 -3
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/structure.md +3 -3
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-brochure/references/template.html +5 -6
- package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-extract/SKILL.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/estate-business/skills/exp-partnership/SKILL.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/estate-business/skills/exp-partnership/references/12-reasons.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/estate-business/skills/exp-partnership/references/business-partnership.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/estate-coaching/skills/bespoke-coaching/references/performance-framework.md +1 -2
- package/payload/premium-plugins/real-agent/plugins/estate-teaching/skills/content-directory/SKILL.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/estate-teaching/skills/content-directory/references/module-delivery.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/leads/skills/prospecting/references/database-matching.md +1 -1
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/SKILL.md +3 -3
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/render.py +1 -1
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/template-inputs.schema.json +1 -1
- package/payload/premium-plugins/real-agent/plugins/vendors/skills/vendor-communication/references/seller-engagement.md +4 -4
- package/payload/premium-plugins/real-agent/plugins/vendors/skills/vendor-communication/references/vendor-updates.md +2 -2
- package/payload/server/maxy-edge.js +6 -2
- package/payload/server/public/assets/admin-6QN-k3zQ.js +1 -0
- package/payload/server/public/assets/admin-6QN-k3zQ.js.br +0 -0
- package/payload/server/public/assets/admin-6QN-k3zQ.js.gz +0 -0
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +777 -349
- package/payload/premium-plugins/real-agent/plugins/preval/skills/property-preval/references/__tests__/adherence.test.py +0 -373
- package/payload/server/public/assets/admin-DGr1HuPg.js +0 -1
- package/payload/server/public/assets/admin-DGr1HuPg.js.br +0 -0
- package/payload/server/public/assets/admin-DGr1HuPg.js.gz +0 -0
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
"""Adherence-gate tests for property-preval (Tasks 157 + 163).
|
|
2
|
-
|
|
3
|
-
Covers:
|
|
4
|
-
|
|
5
|
-
Task 157 provenance causes (agent didn't invent the input):
|
|
6
|
-
- cover-hero-not-subject (slug heuristic; complements 156's symlink check)
|
|
7
|
-
- agent-listings-invented (status set when source property.json had null)
|
|
8
|
-
- market-summary-invented (origin missing or "agent-invented")
|
|
9
|
-
- brand-invented (brand.name without operator override)
|
|
10
|
-
- log-destination-unavailable (observability emit-or-abort)
|
|
11
|
-
|
|
12
|
-
Task 163 causes (replaces 156's sqft gates after EPC removal):
|
|
13
|
-
- epc-certificate-not-supplied (any of the three operator-paste EPC
|
|
14
|
-
fields missing — render.py + hook)
|
|
15
|
-
- observability-missing tool=<name> (one of the 12 expected
|
|
16
|
-
[property-data] tool=<name> log
|
|
17
|
-
lines absent within the budget)
|
|
18
|
-
|
|
19
|
-
Plus the PreToolUse hook red-team (blocks the same causes before
|
|
20
|
-
inputs.json reaches disk).
|
|
21
|
-
|
|
22
|
-
Run with: python3 references/__tests__/adherence.test.py
|
|
23
|
-
"""
|
|
24
|
-
from __future__ import annotations
|
|
25
|
-
import json, os, struct, subprocess, sys, tempfile, unittest, zlib
|
|
26
|
-
from pathlib import Path
|
|
27
|
-
|
|
28
|
-
HERE = Path(__file__).resolve().parent
|
|
29
|
-
REFERENCES = HERE.parent
|
|
30
|
-
PLUGIN_ROOT = REFERENCES.parent.parent.parent
|
|
31
|
-
HOOK = PLUGIN_ROOT / "hooks" / "preval-prompt-required.sh"
|
|
32
|
-
|
|
33
|
-
sys.path.insert(0, str(REFERENCES))
|
|
34
|
-
from render import ( # noqa: E402
|
|
35
|
-
_assert_inputs,
|
|
36
|
-
_assert_observability_logs,
|
|
37
|
-
EXPECTED_PROPERTY_DATA_TOOLS,
|
|
38
|
-
PrevalAbort,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _write_png(path: Path, w: int = 1600, h: int = 1200) -> None:
|
|
43
|
-
"""Minimal valid PNG large enough to clear Task 156's 1200x800 gate."""
|
|
44
|
-
def chunk(tag: bytes, data: bytes) -> bytes:
|
|
45
|
-
return struct.pack(">I", len(data)) + tag + data + struct.pack(">I", zlib.crc32(tag + data) & 0xffffffff)
|
|
46
|
-
sig = b"\x89PNG\r\n\x1a\n"
|
|
47
|
-
ihdr = struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)
|
|
48
|
-
raw = b"".join(b"\x00" + b"\x00\x00\x00" * w for _ in range(h))
|
|
49
|
-
idat = zlib.compress(raw)
|
|
50
|
-
path.write_bytes(sig + chunk(b"IHDR", ihdr) + chunk(b"IDAT", idat) + chunk(b"IEND", b""))
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def _complete_inputs(tmp: Path) -> dict:
|
|
54
|
-
"""An inputs.json that PASSES every 156 + 157 gate."""
|
|
55
|
-
hero = tmp / "hero.png"
|
|
56
|
-
_write_png(hero)
|
|
57
|
-
return {
|
|
58
|
-
"out_dir": str(tmp),
|
|
59
|
-
"filename_stem": "subject",
|
|
60
|
-
"address": "9 Phoenix Drive, Bishop's Stortford, CM23 2UJ",
|
|
61
|
-
"postcode": "CM23 2UJ",
|
|
62
|
-
"generated": "19 May 2026",
|
|
63
|
-
"brand": {
|
|
64
|
-
"name": "Muvin",
|
|
65
|
-
"tagline": "Estate Agents",
|
|
66
|
-
"primary": "#000", "primary_dark": "#000", "accent": "#000",
|
|
67
|
-
"paper": "#fff", "paper_banded": "#fff", "rule": "#000",
|
|
68
|
-
},
|
|
69
|
-
"subject": {
|
|
70
|
-
"cover_hero": str(hero),
|
|
71
|
-
"total_floor_area_m2": 93.2,
|
|
72
|
-
"current_energy_rating": "C",
|
|
73
|
-
"lodgement_date": "2018-04-21",
|
|
74
|
-
},
|
|
75
|
-
"valuation": {
|
|
76
|
-
"avg_asking": 500000, "asking_psf": 450, "avg_sold": 480000,
|
|
77
|
-
"sold_psf": 440, "sold_psf_low": 400, "sold_psf_high": 480,
|
|
78
|
-
"sold_comps": [], "asking_comps": [],
|
|
79
|
-
},
|
|
80
|
-
"area": {
|
|
81
|
-
"crime_rating": "Low", "flood_risk": "Low", "council_tax_band_d": 2000,
|
|
82
|
-
"population": 1000, "crime_breakdown": [], "council_tax_bands": [],
|
|
83
|
-
"headline": "",
|
|
84
|
-
},
|
|
85
|
-
"demand_trend": {
|
|
86
|
-
"demand_rating": "High", "dom": 30, "turnover_pct": 5, "for_sale": 10,
|
|
87
|
-
"growth_series": [], "growth_psf_series": [],
|
|
88
|
-
"rental": {"demand_rating": "High", "dom": 20, "turnover_pct": 4, "for_rent": 5},
|
|
89
|
-
"type_dist": [],
|
|
90
|
-
},
|
|
91
|
-
"market_summary": {
|
|
92
|
-
"headline": "Bishop's Stortford is selling.",
|
|
93
|
-
"paragraphs": ["The market is active.", "Prices held flat YoY."],
|
|
94
|
-
"demand_gauge_position": "62%",
|
|
95
|
-
"price_growth_note": "Up 3% YoY.",
|
|
96
|
-
"demand_note": "High demand.",
|
|
97
|
-
"origin": "operator",
|
|
98
|
-
},
|
|
99
|
-
"agent_listings": [
|
|
100
|
-
{
|
|
101
|
-
"address": "1 Some Road, CM23",
|
|
102
|
-
"price": 600000,
|
|
103
|
-
"status": "Sold",
|
|
104
|
-
"slug": "1-some-road",
|
|
105
|
-
"origin": "operator",
|
|
106
|
-
}
|
|
107
|
-
],
|
|
108
|
-
"agent_overrides": {
|
|
109
|
-
"brand_selected_by_operator": True,
|
|
110
|
-
"listings_status_curated": False,
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class TestAdherenceGate(unittest.TestCase):
|
|
116
|
-
def setUp(self):
|
|
117
|
-
self._tmp = tempfile.TemporaryDirectory()
|
|
118
|
-
self.tmp = Path(self._tmp.name)
|
|
119
|
-
|
|
120
|
-
def tearDown(self):
|
|
121
|
-
self._tmp.cleanup()
|
|
122
|
-
|
|
123
|
-
def _assert_aborts(self, inputs: dict, cause: str):
|
|
124
|
-
with self.assertRaises(PrevalAbort) as ctx:
|
|
125
|
-
_assert_inputs(inputs)
|
|
126
|
-
self.assertEqual(ctx.exception.cause, cause)
|
|
127
|
-
self.assertFalse(any(self.tmp.glob("*.pdf")))
|
|
128
|
-
|
|
129
|
-
def test_clean_run_passes(self):
|
|
130
|
-
_assert_inputs(_complete_inputs(self.tmp))
|
|
131
|
-
|
|
132
|
-
def test_cover_hero_not_subject(self):
|
|
133
|
-
# Plant the hero PNG in a sister property's folder to trigger the
|
|
134
|
-
# 157 slug heuristic. 156's symlink check passes (real file, not
|
|
135
|
-
# a symlink); only the 157 cause should fire.
|
|
136
|
-
sister = self.tmp / "estate-agents" / "muvin" / "properties" / "07-the-old-orchard-rye-street-cm23"
|
|
137
|
-
sister.mkdir(parents=True)
|
|
138
|
-
bad_hero = sister / "hero.png"
|
|
139
|
-
_write_png(bad_hero)
|
|
140
|
-
inputs = _complete_inputs(self.tmp)
|
|
141
|
-
inputs["subject"]["cover_hero"] = str(bad_hero)
|
|
142
|
-
self._assert_aborts(inputs, "cover-hero-not-subject")
|
|
143
|
-
|
|
144
|
-
def test_cover_hero_subject_match_passes(self):
|
|
145
|
-
subject_dir = self.tmp / "estate-agents" / "muvin" / "properties" / "9-phoenix-drive-cm23-2uj"
|
|
146
|
-
subject_dir.mkdir(parents=True)
|
|
147
|
-
good_hero = subject_dir / "hero.png"
|
|
148
|
-
_write_png(good_hero)
|
|
149
|
-
inputs = _complete_inputs(self.tmp)
|
|
150
|
-
inputs["subject"]["cover_hero"] = str(good_hero)
|
|
151
|
-
_assert_inputs(inputs)
|
|
152
|
-
|
|
153
|
-
def test_agent_listings_invented_status(self):
|
|
154
|
-
source = self.tmp / "source.json"
|
|
155
|
-
source.write_text(json.dumps({"status": None, "address": "1 Some Road"}))
|
|
156
|
-
inputs = _complete_inputs(self.tmp)
|
|
157
|
-
inputs["agent_listings"][0]["origin"] = str(source)
|
|
158
|
-
inputs["agent_overrides"]["listings_status_curated"] = False
|
|
159
|
-
self._assert_aborts(inputs, "agent-listings-invented")
|
|
160
|
-
|
|
161
|
-
def test_agent_listings_curated_override_passes(self):
|
|
162
|
-
source = self.tmp / "source.json"
|
|
163
|
-
source.write_text(json.dumps({"status": None, "address": "1 Some Road"}))
|
|
164
|
-
inputs = _complete_inputs(self.tmp)
|
|
165
|
-
inputs["agent_listings"][0]["origin"] = str(source)
|
|
166
|
-
inputs["agent_overrides"]["listings_status_curated"] = True
|
|
167
|
-
_assert_inputs(inputs)
|
|
168
|
-
|
|
169
|
-
def test_market_summary_invented_missing_origin(self):
|
|
170
|
-
inputs = _complete_inputs(self.tmp)
|
|
171
|
-
inputs["market_summary"].pop("origin")
|
|
172
|
-
self._assert_aborts(inputs, "market-summary-invented")
|
|
173
|
-
|
|
174
|
-
def test_market_summary_invented_explicit(self):
|
|
175
|
-
inputs = _complete_inputs(self.tmp)
|
|
176
|
-
inputs["market_summary"]["origin"] = "agent-invented"
|
|
177
|
-
self._assert_aborts(inputs, "market-summary-invented")
|
|
178
|
-
|
|
179
|
-
def test_brand_invented(self):
|
|
180
|
-
inputs = _complete_inputs(self.tmp)
|
|
181
|
-
inputs["agent_overrides"]["brand_selected_by_operator"] = False
|
|
182
|
-
self._assert_aborts(inputs, "brand-invented")
|
|
183
|
-
|
|
184
|
-
def test_epc_certificate_not_supplied_missing_m2(self):
|
|
185
|
-
inputs = _complete_inputs(self.tmp)
|
|
186
|
-
del inputs["subject"]["total_floor_area_m2"]
|
|
187
|
-
self._assert_aborts(inputs, "epc-certificate-not-supplied")
|
|
188
|
-
|
|
189
|
-
def test_epc_certificate_not_supplied_missing_rating(self):
|
|
190
|
-
inputs = _complete_inputs(self.tmp)
|
|
191
|
-
inputs["subject"]["current_energy_rating"] = None
|
|
192
|
-
self._assert_aborts(inputs, "epc-certificate-not-supplied")
|
|
193
|
-
|
|
194
|
-
def test_epc_certificate_not_supplied_missing_lodgement(self):
|
|
195
|
-
inputs = _complete_inputs(self.tmp)
|
|
196
|
-
inputs["subject"]["lodgement_date"] = ""
|
|
197
|
-
self._assert_aborts(inputs, "epc-certificate-not-supplied")
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
class TestPreToolUseHook(unittest.TestCase):
|
|
201
|
-
def _run_hook(self, tool_name: str, file_path: str, content_obj: dict) -> tuple[int, str]:
|
|
202
|
-
payload = json.dumps({
|
|
203
|
-
"tool_name": tool_name,
|
|
204
|
-
"tool_input": {"file_path": file_path, "content": json.dumps(content_obj)},
|
|
205
|
-
})
|
|
206
|
-
result = subprocess.run(
|
|
207
|
-
["bash", str(HOOK)],
|
|
208
|
-
input=payload,
|
|
209
|
-
capture_output=True,
|
|
210
|
-
text=True,
|
|
211
|
-
)
|
|
212
|
-
return result.returncode, result.stderr
|
|
213
|
-
|
|
214
|
-
def test_hook_blocks_market_summary_invented(self):
|
|
215
|
-
with tempfile.TemporaryDirectory() as tmp:
|
|
216
|
-
inputs = _complete_inputs(Path(tmp))
|
|
217
|
-
inputs["market_summary"]["origin"] = "agent-invented"
|
|
218
|
-
code, stderr = self._run_hook(
|
|
219
|
-
"Write",
|
|
220
|
-
f"{tmp}/preval/CM232UJ-2026-05-19/inputs.json",
|
|
221
|
-
inputs,
|
|
222
|
-
)
|
|
223
|
-
self.assertEqual(code, 2, msg=stderr)
|
|
224
|
-
self.assertIn("market-summary-invented", stderr)
|
|
225
|
-
|
|
226
|
-
def test_hook_blocks_brand_invented(self):
|
|
227
|
-
with tempfile.TemporaryDirectory() as tmp:
|
|
228
|
-
inputs = _complete_inputs(Path(tmp))
|
|
229
|
-
inputs["agent_overrides"]["brand_selected_by_operator"] = False
|
|
230
|
-
code, stderr = self._run_hook(
|
|
231
|
-
"Write",
|
|
232
|
-
f"{tmp}/preval/CM232UJ-2026-05-19/inputs.json",
|
|
233
|
-
inputs,
|
|
234
|
-
)
|
|
235
|
-
self.assertEqual(code, 2, msg=stderr)
|
|
236
|
-
self.assertIn("brand-invented", stderr)
|
|
237
|
-
|
|
238
|
-
def test_hook_passthrough_unrelated_path(self):
|
|
239
|
-
code, _ = self._run_hook(
|
|
240
|
-
"Write",
|
|
241
|
-
"/tmp/some-other-file.json",
|
|
242
|
-
{"hello": "world"},
|
|
243
|
-
)
|
|
244
|
-
self.assertEqual(code, 0)
|
|
245
|
-
|
|
246
|
-
def test_hook_passthrough_unrelated_tool(self):
|
|
247
|
-
code, _ = self._run_hook(
|
|
248
|
-
"Bash",
|
|
249
|
-
"/whatever/preval/inputs.json",
|
|
250
|
-
{},
|
|
251
|
-
)
|
|
252
|
-
self.assertEqual(code, 0)
|
|
253
|
-
|
|
254
|
-
def test_hook_blocks_epc_certificate_not_supplied(self):
|
|
255
|
-
with tempfile.TemporaryDirectory() as tmp:
|
|
256
|
-
inputs = _complete_inputs(Path(tmp))
|
|
257
|
-
inputs["subject"]["current_energy_rating"] = None
|
|
258
|
-
code, stderr = self._run_hook(
|
|
259
|
-
"Write",
|
|
260
|
-
f"{tmp}/preval/CM232UJ-2026-05-19/inputs.json",
|
|
261
|
-
inputs,
|
|
262
|
-
)
|
|
263
|
-
self.assertEqual(code, 2, msg=stderr)
|
|
264
|
-
self.assertIn("epc-certificate-not-supplied", stderr)
|
|
265
|
-
self.assertIn("current_energy_rating", stderr)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
class TestObservability(unittest.TestCase):
|
|
269
|
-
def test_log_destination_unavailable_aborts(self):
|
|
270
|
-
from render import _pick_log_path
|
|
271
|
-
ro = Path("/dev/null/cannot-write-here")
|
|
272
|
-
old_home = os.environ.get("HOME")
|
|
273
|
-
with tempfile.TemporaryDirectory() as tmp:
|
|
274
|
-
holder = Path(tmp) / "not-a-dir"
|
|
275
|
-
holder.write_text("")
|
|
276
|
-
os.environ["HOME"] = str(holder)
|
|
277
|
-
try:
|
|
278
|
-
with self.assertRaises(PrevalAbort) as ctx:
|
|
279
|
-
_pick_log_path(ro)
|
|
280
|
-
self.assertEqual(ctx.exception.cause, "log-destination-unavailable")
|
|
281
|
-
finally:
|
|
282
|
-
if old_home is not None:
|
|
283
|
-
os.environ["HOME"] = old_home
|
|
284
|
-
else:
|
|
285
|
-
del os.environ["HOME"]
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
class TestObservabilityWatchdog(unittest.TestCase):
|
|
289
|
-
"""Task 163 — 12-call PropertyData fan-out watchdog."""
|
|
290
|
-
|
|
291
|
-
def setUp(self):
|
|
292
|
-
self._tmp = tempfile.TemporaryDirectory()
|
|
293
|
-
self.tmp = Path(self._tmp.name)
|
|
294
|
-
self.log_path = self.tmp / "preval.log"
|
|
295
|
-
|
|
296
|
-
def tearDown(self):
|
|
297
|
-
self._tmp.cleanup()
|
|
298
|
-
|
|
299
|
-
def _write_log(self, present_tools: list[str]) -> None:
|
|
300
|
-
lines = [
|
|
301
|
-
f"[property-data] tool={name} account=local postcode=CM232UJ status=ok ms=42"
|
|
302
|
-
for name in present_tools
|
|
303
|
-
]
|
|
304
|
-
self.log_path.write_text("\n".join(lines) + "\n")
|
|
305
|
-
|
|
306
|
-
def test_all_12_present_passes(self):
|
|
307
|
-
self._write_log(list(EXPECTED_PROPERTY_DATA_TOOLS))
|
|
308
|
-
_assert_observability_logs(self.log_path, deadline_s=0.0)
|
|
309
|
-
|
|
310
|
-
def test_missing_growth_psf_aborts(self):
|
|
311
|
-
present = [t for t in EXPECTED_PROPERTY_DATA_TOOLS if t != "property-data-growth-psf"]
|
|
312
|
-
self._write_log(present)
|
|
313
|
-
with self.assertRaises(PrevalAbort) as ctx:
|
|
314
|
-
_assert_observability_logs(self.log_path, deadline_s=0.0)
|
|
315
|
-
self.assertEqual(
|
|
316
|
-
ctx.exception.cause,
|
|
317
|
-
"observability-missing tool=property-data-growth-psf",
|
|
318
|
-
)
|
|
319
|
-
self.assertIn("property-data-growth-psf", ctx.exception.hint)
|
|
320
|
-
|
|
321
|
-
def test_missing_flood_risk_aborts(self):
|
|
322
|
-
present = [t for t in EXPECTED_PROPERTY_DATA_TOOLS if t != "property-data-flood-risk"]
|
|
323
|
-
self._write_log(present)
|
|
324
|
-
with self.assertRaises(PrevalAbort) as ctx:
|
|
325
|
-
_assert_observability_logs(self.log_path, deadline_s=0.0)
|
|
326
|
-
self.assertEqual(
|
|
327
|
-
ctx.exception.cause,
|
|
328
|
-
"observability-missing tool=property-data-flood-risk",
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
def test_polls_until_late_arriving_line_lands(self):
|
|
332
|
-
"""The watchdog must keep polling within the budget; a late arrival
|
|
333
|
-
before the deadline is a pass, not an abort. Wall-clock waits are
|
|
334
|
-
replaced by injected _now/_sleep so the test stays fast."""
|
|
335
|
-
present = [t for t in EXPECTED_PROPERTY_DATA_TOOLS if t != "property-data-prices"]
|
|
336
|
-
self._write_log(present)
|
|
337
|
-
ticks = iter([0.0, 1.0, 2.0]) # never reaches deadline_s=10
|
|
338
|
-
appended = []
|
|
339
|
-
|
|
340
|
-
def fake_sleep(s):
|
|
341
|
-
appended.append(s)
|
|
342
|
-
with self.log_path.open("a") as f:
|
|
343
|
-
f.write(
|
|
344
|
-
"[property-data] tool=property-data-prices account=local postcode=CM232UJ status=ok ms=99\n"
|
|
345
|
-
)
|
|
346
|
-
|
|
347
|
-
_assert_observability_logs(
|
|
348
|
-
self.log_path,
|
|
349
|
-
deadline_s=10.0,
|
|
350
|
-
poll_s=2.0,
|
|
351
|
-
_now=lambda: next(ticks),
|
|
352
|
-
_sleep=fake_sleep,
|
|
353
|
-
)
|
|
354
|
-
self.assertEqual(appended, [2.0])
|
|
355
|
-
|
|
356
|
-
def test_unreadable_log_aborts_at_deadline(self):
|
|
357
|
-
"""A log path that can't be read is treated as missing tools — abort
|
|
358
|
-
once the budget elapses, name a missing tool. No silent skip."""
|
|
359
|
-
# Don't write the log file at all.
|
|
360
|
-
ticks = iter([0.0, 100.0])
|
|
361
|
-
with self.assertRaises(PrevalAbort) as ctx:
|
|
362
|
-
_assert_observability_logs(
|
|
363
|
-
self.log_path,
|
|
364
|
-
deadline_s=60.0,
|
|
365
|
-
poll_s=2.0,
|
|
366
|
-
_now=lambda: next(ticks),
|
|
367
|
-
_sleep=lambda s: None,
|
|
368
|
-
)
|
|
369
|
-
self.assertTrue(ctx.exception.cause.startswith("observability-missing tool="))
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
if __name__ == "__main__":
|
|
373
|
-
unittest.main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./chunk-CltuBf4Z.js";import{B as t,D as n,K as r,V as i,W as a,a as o,l as s,m as c,p as l,s as u,v as d}from"./useSubAccountSwitcher-CJKjEPNN.js";import{n as f,t as p}from"./AdminLoginScreens-bksN0XPe.js";import{s as m}from"./useVoiceRecorder-ChnBrzbZ.js";import{a as h,b as g,f as _,t as v,y as ee}from"./AdminShell-BMPEWNZk.js";import{a as y,i as b,n as x,r as te}from"./page-BWFHRIAH.js";import{t as S}from"./chevron-left-DqYv3oFh.js";import{t as ne}from"./chevron-right-CQfPGsFb.js";import{t as re}from"./file-text-DMKw3nIk.js";import"./graph-labels-BZgd0L6n.js";var C=a(),w=e(r(),1),T=t();function E({onOpen:e}){return(0,T.jsx)(`footer`,{className:`admin-footer`,children:(0,T.jsxs)(`div`,{className:`powered-by`,role:`button`,tabIndex:0,onClick:e,onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),e())},"aria-label":`Powered by Claude Code — show details`,children:[(0,T.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`powered-by-icon`}),(0,T.jsx)(`span`,{children:`Powered by Claude Code`})]})})}function D({sessionId:e,projectDir:t,sessionKey:n,contactName:r,onBack:i}){return(0,T.jsxs)(`div`,{className:`wa-web`,children:[(0,T.jsxs)(`header`,{className:`wa-web-header`,children:[i&&(0,T.jsx)(`button`,{type:`button`,className:`wa-web-back`,onClick:i,"aria-label":`Back`,children:(0,T.jsx)(S,{size:20})}),(0,T.jsx)(`span`,{className:`wa-web-avatar`,"aria-hidden":!0,children:(0,T.jsx)(y,{size:20})}),(0,T.jsx)(`div`,{className:`wa-web-titles`,children:(0,T.jsx)(`span`,{className:`wa-web-name`,children:r})})]}),(0,T.jsx)(`div`,{className:`wa-web-body`,children:(0,T.jsx)(m,{sessionId:e,projectDir:t,sessionKey:n,forceDeliveredOnly:!0})})]})}var O=6e4,k=60*O,A=24*k,j=O,M=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],N=[`Sun`,`Mon`,`Tue`,`Wed`,`Thu`,`Fri`,`Sat`];function P(e){return e<10?`0${e}`:String(e)}function F(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function I(e,t){if(!Number.isFinite(e)||e<=0||!Number.isFinite(t))return`—`;let n=t-e;if(n<-j)return`—`;let r=n<0?0:n;if(r<O)return`just now`;if(r<k)return`${Math.floor(r/O)}m`;if(r<A)return`${Math.floor(r/k)}h`;let i=new Date(t),a=new Date(e),o=Math.round((F(i)-F(a))/A);if(o===1)return`yesterday`;if(o>=2&&o<=6)return N[a.getDay()];let s=P(a.getDate()),c=M[a.getMonth()];return a.getFullYear()===i.getFullYear()?`${s} ${c}`:`${s} ${c} ${a.getFullYear()}`}var ie={whatsapp:`WhatsApp`,telegram:`Telegram`,webchat:`Web chat`};function L({variant:e=`row`,count:t=1}){return(0,T.jsx)(T.Fragment,{children:Array.from({length:t},(t,n)=>(0,T.jsx)(`span`,{className:`dashboard-skeleton dashboard-skeleton--${e}`,"data-testid":`dashboard-skeleton`,"aria-hidden":`true`},n))})}var R=6e4;function ae(e){return e<12?`morning`:e<18?`afternoon`:`evening`}function z(e){return e&&e.trim().split(/\s+/)[0]||`there`}function B(e){if(!e)return`everything is running normally.`;let t=e.cpuPct,n=e.memUsedPct;return t!==null&&t>=.98||n!==null&&n>=.98?`system load is critical.`:t!==null&&t>=.9||n!==null&&n>=.9?`system load is high.`:`everything is running normally.`}function V(e){return e==null?`—`:`${Math.round(e*100)}%`}function H(e){return e.operatorName??e.whatsappName??e.senderId??e.title}function U(e,t){if(!e)return!1;let n=Date.parse(e);if(!Number.isFinite(n))return!1;let r=new Date(n),i=new Date(t);return r.getFullYear()===i.getFullYear()&&r.getMonth()===i.getMonth()&&r.getDate()===i.getDate()}function W(e){return e?e.replace(/^claude-/,``):null}var G=new Set([`sessions`,`conversations`,`tasks`,`artefacts`,`skills`,`stats`]),K=!1;function q(e,t,n,r){let i=e=>t.get(e)??null,a=r?r.getEntriesByType(`navigation`)[0]:void 0,o=r?r.getEntriesByType(`resource`).filter(e=>new URL(e.name,`http://x`).pathname.startsWith(`/assets/`)):[],s=e=>e===void 0||!Number.isFinite(e)?null:Math.round(e),c=e=>e?s(e):null;return{batchMs:e,sessionsMs:i(`sessions`),conversationsMs:i(`conversations`),tasksMs:i(`tasks`),artefactsMs:i(`artefacts`),skillsMs:i(`skills`),statsMs:i(`stats`),failed:[...G].filter(e=>n.has(e)).join(`,`)||`none`,ttfbMs:s(a?.responseStart),domContentLoadedMs:c(a?.domContentLoadedEventEnd),loadMs:c(a?.loadEventEnd),assetCount:o.length,assetBytes:o.reduce((e,t)=>e+(t.transferSize||0),0),assetMs:o.length?s(Math.max(...o.map(e=>e.responseEnd))):null}}function J({cacheKey:e,userName:t,onSelectWhatsappConversation:r}){let a=c(e),[l,f]=(0,w.useState)(null),[p,m]=(0,w.useState)(null),[h,v]=(0,w.useState)(null),y=(0,w.useRef)(!1),[b,x]=(0,w.useState)(null),[S,C]=(0,w.useState)(null),[E,D]=(0,w.useState)(null),[O,k]=(0,w.useState)(null),[A,j]=(0,w.useState)(new Set),[M,N]=(0,w.useState)(()=>new Set),P=(0,w.useCallback)(e=>{N(t=>t.has(e)?t:new Set(t).add(e))},[]),F=Date.now(),G=(0,w.useRef)(!1),J=(0,w.useRef)(new Map),Y=(0,w.useRef)(new Set);(0,w.useEffect)(()=>{if(!e)return;let t=!1;async function n(e,n,r,i){let o=Date.now();try{let s=await a(n);if(!s.ok)throw Error(`status ${s.status}`);let c=await s.json();t||i(r(c)),console.info(`[admin-ui] op=dashboard-fetch slice=${e} url=${n} outcome=ok ms=${Date.now()-o}`)}catch(t){Y.current.add(e),console.error(`[admin-ui] dashboard-fetch-failed slice=${e} url=${n} ms=${Date.now()-o} reason=${t instanceof Error?t.message:String(t)}`)}finally{J.current.set(e,Date.now()-o),t||P(e)}}let r={"sidebar-sessions":()=>n(`sessions`,`/api/admin/sidebar-sessions`,e=>e.sessions??[],f),"conversations-all":()=>n(`conversations`,`/api/whatsapp-reader/conversations-all`,e=>e.conversations??[],m),"tasks-list":()=>n(`tasks`,`/api/admin/tasks-list`,e=>e,C),"sidebar-artefacts":()=>n(`artefacts`,`/api/admin/sidebar-artefacts`,e=>e.artefacts??[],D),skills:()=>n(`skills`,`/api/admin/skills`,e=>e.skills??[],k)};async function o(){if(G.current)return;G.current=!0;let e=Date.now();try{await Promise.all([...Object.values(r).map(e=>e()),n(`stats`,`/api/admin/system-stats`,e=>e,x)])}finally{G.current=!1;let t=Date.now()-e;if(console.info(`[admin-ui] op=dashboard-refresh-settled ms=${t}`),!K){K=!0;try{let e=q(t,J.current,Y.current,typeof performance>`u`?null:performance);fetch(`/api/_client-error`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({kind:`event`,source:`dashboard-load`,...e}),keepalive:!0}).catch(()=>{})}catch{}}}}o();let s=null;try{s=new EventSource(i(`/api/admin/events`,e)),s.onmessage=e=>{if(document.visibilityState===`visible`)try{let{resource:t}=JSON.parse(e.data),n=t?r[t]:void 0;n&&n()}catch{}},s.onerror=()=>{console.error(`[admin-ui] dashboard-events stream error`)}}catch(e){console.error(`[admin-ui] dashboard-events unavailable reason=${e instanceof Error?e.message:String(e)}`)}let c=setInterval(()=>{document.visibilityState===`visible`&&o()},R),l=()=>{document.visibilityState===`visible`&&o()};return document.addEventListener(`visibilitychange`,l),()=>{t=!0,clearInterval(c),s?.close(),document.removeEventListener(`visibilitychange`,l)}},[e,a]);let X=(0,w.useMemo)(()=>(l??[]).filter(e=>!e.isSubagent),[l]),Z=(0,w.useMemo)(()=>X.filter(e=>e.live),[X]),oe=(0,w.useMemo)(()=>(p??[]).filter(e=>U(e.lastMessageAt,F)).length,[p,F]),se=S?.open.length??0,Q=(0,w.useMemo)(()=>{let e=new Map;for(let t of p??[]){let n=e.get(t.channel)??[];n.push(t),e.set(t.channel,n)}return[...e.entries()].map(([e,t])=>{let n=t.reduce((e,t)=>t.lastMessageAt&&(!e||Date.parse(t.lastMessageAt)>Date.parse(e.lastMessageAt??``))?t:e,null);return{channel:e,count:t.length,preview:n?H(n):``,rows:t}})},[p]);(0,w.useEffect)(()=>{y.current||Q.length!==0&&(y.current=!0,v(Q[0].channel))},[Q]);let ce=(0,w.useCallback)(async e=>{if(!A.has(e)){j(t=>new Set(t).add(e));try{let t=await a(`/api/admin/session-stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sessionId:e})});if(!t.ok){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} status=${t.status}`);return}console.info(`[admin-ui] dashboard-session-stop sessionId=${e}`),f(t=>(t??[]).map(t=>t.sessionId===e?{...t,live:!1}:t))}catch(t){console.error(`[admin-ui] dashboard-session-stop-failed sessionId=${e} reason=${t instanceof Error?t.message:String(t)}`)}finally{j(t=>{let n=new Set(t);return n.delete(e),n})}}},[a,A]),le=(0,w.useCallback)(t=>{if(!e||!t.downloadPath){console.error(`[admin-ui] dashboard-artefact-download-blocked id=${t.id} reason=${e?`not-downloadable`:`no-cache-key`}`);return}te(e,t.downloadPath,t.downloadRoot??`data`)},[e]),$=ae(new Date(F).getHours());return(0,T.jsxs)(`div`,{className:`dashboard-home`,children:[(0,T.jsx)(`p`,{className:`dashboard-greeting`,children:M.has(`stats`)?`Good ${$}, ${z(t)} — ${B(b)}`:`Good ${$}, ${z(t)}`}),(0,T.jsxs)(`div`,{className:`dashboard-stats`,children:[(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Live sessions`}),M.has(`sessions`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:Z.length}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`of `,X.length,` total`]})]}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Messages today`}),M.has(`conversations`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:oe}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`a`,{className:`admin-stat-card dashboard-stat-card dashboard-stat-card--link`,href:`/tasks`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Open tasks`}),M.has(`tasks`)?(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:se}):(0,T.jsx)(L,{variant:`value`})]}),(0,T.jsxs)(`div`,{className:`admin-stat-card dashboard-stat-card`,children:[(0,T.jsx)(`span`,{className:`dashboard-stat-label`,children:`Host CPU`}),M.has(`stats`)?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`span`,{className:`dashboard-stat-value`,children:V(b?.cpuPct??null)}),(0,T.jsxs)(`span`,{className:`dashboard-stat-delta`,children:[`RAM `,V(b?.memUsedPct??null)]})]}):(0,T.jsx)(L,{variant:`value`})]})]}),(0,T.jsxs)(`div`,{className:`dashboard-columns`,children:[(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Live now`}),M.has(`sessions`)?Z.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No live sessions right now.`}):Z.map(e=>{let t=[e.sessionId.slice(0,8),W(e.model),I(Date.parse(e.startedAt),F)].filter(Boolean).join(` · `);return(0,T.jsxs)(`div`,{className:`admin-card dashboard-live-card`,children:[(0,T.jsx)(`span`,{className:`admin-status-dot is-live`}),(0,T.jsxs)(`div`,{className:`dashboard-live-main`,children:[(0,T.jsx)(`span`,{className:`dashboard-live-name`,children:e.title}),(0,T.jsx)(`span`,{className:`dashboard-live-meta`,children:t})]}),(0,T.jsx)(`a`,{className:`admin-btn-cta dashboard-open-btn`,href:`/chat?session=${encodeURIComponent(e.sessionId)}`,children:`Open`}),(0,T.jsx)(`button`,{type:`button`,className:`dashboard-stop-btn`,"aria-label":`Stop ${e.title}`,disabled:A.has(e.sessionId),onClick:()=>void ce(e.sessionId),children:(0,T.jsx)(d,{size:12})})]},e.sessionId)}):(0,T.jsx)(L,{variant:`card`,count:2}),(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Recent artefacts`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-artefacts`,children:M.has(`artefacts`)?(E??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No recent artefacts.`}):(E??[]).slice(0,6).map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-artefact-row`,onClick:()=>le(e),children:[(0,T.jsx)(`span`,{className:`dashboard-artefact-icon`,children:e.kind===`agent-template`?(0,T.jsx)(g,{size:16}):(0,T.jsx)(re,{size:16})}),(0,T.jsx)(`div`,{className:`dashboard-artefact-body`,children:(0,T.jsx)(`span`,{className:`dashboard-artefact-name`,children:e.name})}),(0,T.jsx)(`span`,{className:`dashboard-artefact-time`,children:I(Date.parse(e.updatedAt),F)})]},e.id)):(0,T.jsx)(L,{count:3})}),(0,T.jsx)(`a`,{className:`admin-section-label dashboard-col-label dashboard-skills-label`,href:`/skills`,children:`Skills`}),(0,T.jsx)(`div`,{className:`admin-card dashboard-skills`,children:M.has(`skills`)?(O??[]).length===0?(0,T.jsx)(`div`,{className:`dashboard-empty`,children:`No skills yet.`}):(O??[]).map(e=>(0,T.jsxs)(`a`,{className:`admin-row dashboard-skill-row`,href:`/skills`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-icon`,children:(0,T.jsx)(_,{size:16})}),(0,T.jsxs)(`div`,{className:`dashboard-skill-body`,children:[(0,T.jsx)(`span`,{className:`dashboard-skill-name`,children:e.skill}),(0,T.jsx)(`span`,{className:`dashboard-skill-plugin`,children:e.plugin})]})]},`${e.plugin}/${e.skill}`)):(0,T.jsx)(L,{count:2})})]}),(0,T.jsxs)(`div`,{className:`dashboard-col`,children:[(0,T.jsx)(`span`,{className:`admin-section-label dashboard-col-label`,children:`Channels`}),M.has(`conversations`)?Q.length===0?(0,T.jsx)(`div`,{className:`admin-card dashboard-empty`,children:`No channel activity.`}):Q.map(e=>{let t=h===e.channel;return(0,T.jsxs)(`div`,{className:`admin-card dashboard-channel-card`,children:[(0,T.jsxs)(`button`,{type:`button`,className:`dashboard-channel-head`,"aria-expanded":t,onClick:()=>v(t=>t===e.channel?null:e.channel),children:[(0,T.jsx)(`span`,{className:`dashboard-channel-glyph`,children:e.channel===`whatsapp`||e.channel===`telegram`?(0,T.jsx)(s,{channel:e.channel,size:16}):(0,T.jsx)(n,{size:16})}),(0,T.jsx)(`span`,{className:`dashboard-channel-name`,children:ie[e.channel]??e.channel}),(0,T.jsx)(`span`,{className:`dashboard-channel-badge`,children:e.count}),(0,T.jsx)(`span`,{className:`dashboard-channel-chevron`,children:t?(0,T.jsx)(ee,{size:14}):(0,T.jsx)(ne,{size:14})})]}),t?(0,T.jsx)(`div`,{className:`dashboard-channel-convs`,children:e.rows.map(e=>(0,T.jsxs)(`button`,{type:`button`,className:`admin-row dashboard-channel-conv-row`,onClick:()=>r(e),title:e.title,children:[(0,T.jsx)(`span`,{className:`dashboard-channel-conv-name`,children:o(e)}),(0,T.jsx)(`span`,{className:`dashboard-channel-conv-tag`,children:e.isHouse?`House`:`Client`}),e.lastMessageAt&&(0,T.jsx)(`span`,{className:`dashboard-channel-conv-time`,children:I(Date.parse(e.lastMessageAt),F)})]},u(e)))}):e.preview&&(0,T.jsx)(`span`,{className:`dashboard-channel-preview`,children:e.preview})]},e.channel)}):(0,T.jsx)(L,{variant:`card`,count:2})]})]})]})}function Y(){let e=f(),[t,n]=(0,w.useState)(!1);(0,w.useEffect)(()=>{if(!t)return;let e=e=>{e.key===`Escape`&&n(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[t]);let r=(0,w.useCallback)(async()=>{let t=e.claudeInfo!=null;if(n(!0),t){console.info(`[admin-ui] claude-info-open cached=true ms=0`);return}let r=Date.now();if(!e.cacheKey){console.error(`[admin-ui] claude-info-fetch-skipped reason=no-session-key`);return}try{let t=await fetch(`/api/admin/claude-info?session_key=${encodeURIComponent(e.cacheKey)}`);if(t.ok){let n=await t.json();e.setClaudeInfo(n)}console.info(`[admin-ui] claude-info-open cached=false ms=${Date.now()-r}`)}catch(e){console.error(`[admin-ui] claude-info-fetch-failed ms=${Date.now()-r} error="${e instanceof Error?e.message:String(e)}"`)}},[e]),i=(0,w.useCallback)(({code:t,path:n})=>{console.warn(`[admin-auth] outcome=chat-tab-logout-on-401 code=${t} path=${n}`),e.handleLogout()},[e]);return e.appState===`chat`?(0,T.jsx)(l,{cacheKey:e.cacheKey,onSessionExpired:i,surface:`chat`,children:(0,T.jsx)(v,{cacheKey:e.cacheKey,businessName:e.businessName,sessionId:e.sessionId,onLogout:e.handleLogout,onDisconnect:e.handleDisconnect,disconnecting:e.disconnecting,claudeConnected:e.claudeConnected,onConnectClaude:()=>e.setAppState(`connect-claude`),userName:e.userName,userAvatar:e.userAvatar,role:e.role,footer:(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(E,{onOpen:r}),(0,T.jsx)(h,{show:t,onClose:()=>n(!1),claudeInfo:e.claudeInfo,messages:[],sessionElapsed:0,sessionId:e.sessionId,cacheKey:e.cacheKey})]}),children:t=>(0,T.jsx)(T.Fragment,{children:t.dataOpen&&e.cacheKey?(0,T.jsx)(x,{cacheKey:e.cacheKey}):t.selectedWhatsapp&&e.cacheKey?t.selectedWhatsapp.source===`store`&&t.selectedWhatsapp.remoteJid&&t.selectedWhatsapp.accountId?(0,T.jsx)(b,{accountId:t.selectedWhatsapp.accountId,remoteJid:t.selectedWhatsapp.remoteJid,contactName:o(t.selectedWhatsapp),sessionKey:e.cacheKey,onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(D,{sessionId:t.selectedWhatsapp.sessionId,projectDir:t.selectedWhatsapp.projectDir,sessionKey:e.cacheKey,contactName:o(t.selectedWhatsapp),onBack:t.onClearWhatsapp},u(t.selectedWhatsapp)):(0,T.jsx)(J,{cacheKey:e.cacheKey,userName:e.userName,onSelectWhatsappConversation:t.onSelectWhatsappConversation})})})}):(0,T.jsx)(p,{auth:e})}(0,C.createRoot)(document.getElementById(`root`)).render((0,T.jsx)(Y,{}));
|
|
Binary file
|
|
Binary file
|