zcode-supervisor 0.0.1__py3-none-any.whl

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.
tools/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ """Project command modules."""
2
+
@@ -0,0 +1,16 @@
1
+ """Python entrypoint wrapper for the bundled Node controller."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+
10
+ def main(argv: list[str] | None = None) -> int:
11
+ controller = Path(__file__).resolve().with_name("zcodectl.mjs")
12
+ try:
13
+ return subprocess.call(["node", str(controller), *(argv if argv is not None else sys.argv[1:])])
14
+ except FileNotFoundError:
15
+ print("zcodectl requires Node.js on PATH. Install Node.js and retry.", file=sys.stderr)
16
+ return 127
@@ -0,0 +1,106 @@
1
+ export function usageSnapshotExpression() {
2
+ return String.raw`(() => {
3
+ const bodyText = document.body?.innerText || "";
4
+ const parseHumanNumber = (raw, suffix) => {
5
+ const numeric = Number(String(raw).replace(/,/g, ""));
6
+ if (!Number.isFinite(numeric)) return null;
7
+ const multiplier = suffix === "K" ? 1_000 : suffix === "M" ? 1_000_000 : suffix === "B" ? 1_000_000_000 : 1;
8
+ return numeric * multiplier;
9
+ };
10
+ const lines = bodyText.split(/\n+/).map((line) => line.trim()).filter(Boolean);
11
+ const relevant = lines.filter((line) =>
12
+ /\b(token|tokens|quota|usage|remaining|used|coding plan|prompt pool|weekly|monthly|context|glm)\b/i.test(line),
13
+ );
14
+ const tokenCandidates = [];
15
+ const quotaPercentCandidates = [];
16
+ for (const line of relevant) {
17
+ for (const match of line.matchAll(/([\d,.]+)\s*([KMB])?\s*(?:tokens?|token)\b/gi)) {
18
+ const value = parseHumanNumber(match[1], match[2]?.toUpperCase());
19
+ if (value !== null) tokenCandidates.push({ line, value });
20
+ }
21
+ for (const match of line.matchAll(/(\d+(?:\.\d+)?)\s*%/g)) {
22
+ const value = Number(match[1]);
23
+ if (Number.isFinite(value)) quotaPercentCandidates.push({ line, value });
24
+ }
25
+ }
26
+ const tokenBest =
27
+ tokenCandidates.find((item) => /\b(total|token usage|all time)\b/i.test(item.line)) ||
28
+ tokenCandidates[0] ||
29
+ null;
30
+ const quotaBest =
31
+ quotaPercentCandidates.find((item) => /\b(quota|remaining|prompt pool|weekly|monthly)\b/i.test(item.line)) ||
32
+ quotaPercentCandidates.find((item) => !/\bcontext\b/i.test(item.line)) ||
33
+ quotaPercentCandidates[0] ||
34
+ null;
35
+ return {
36
+ captured_at: new Date().toISOString(),
37
+ title: document.title,
38
+ visible_usage_lines: relevant.slice(0, 80),
39
+ token_candidates: tokenCandidates.slice(0, 20),
40
+ quota_percent_candidates: quotaPercentCandidates.slice(0, 20),
41
+ best: {
42
+ tokens_total: tokenBest?.value ?? null,
43
+ tokens_line: tokenBest?.line ?? null,
44
+ quota_percent: quotaBest?.value ?? null,
45
+ quota_percent_line: quotaBest?.line ?? null,
46
+ },
47
+ };
48
+ })()`;
49
+ }
50
+
51
+ export function openUsageExpression() {
52
+ return `(() => {
53
+ const dispatchClick = (el) => {
54
+ const r = el.getBoundingClientRect();
55
+ const x = Math.round(r.x + r.width / 2);
56
+ const y = Math.round(r.y + r.height / 2);
57
+ for (const type of ['pointerdown', 'mousedown', 'pointerup', 'mouseup', 'click']) {
58
+ el.dispatchEvent(new MouseEvent(type, { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y }));
59
+ }
60
+ return { x, y };
61
+ };
62
+ const clickCandidate = (needles) => {
63
+ const candidates = Array.from(document.querySelectorAll('button,[role=button],a,[role=menuitem],[data-testid]'));
64
+ const el = candidates.find((node) => {
65
+ const text = (node.innerText || node.textContent || node.getAttribute('aria-label') || '').trim().toLowerCase();
66
+ const testid = (node.getAttribute('data-testid') || '').toLowerCase();
67
+ const rect = node.getBoundingClientRect();
68
+ const visible = rect.width > 0 && rect.height > 0;
69
+ return visible && needles.some((needle) => text.includes(needle) || testid.includes(needle));
70
+ });
71
+ if (!el) return null;
72
+ return { text: (el.innerText || el.textContent || el.getAttribute('aria-label') || '').trim(), ...dispatchClick(el) };
73
+ };
74
+ const direct = clickCandidate(['usage stats', 'usage', 'quota', 'coding plan']);
75
+ if (direct) return { ok: true, phase: 'usage', clicked: direct };
76
+ const settings = clickCandidate(['settings', 'preferences']);
77
+ if (settings) return { ok: true, phase: 'settings', clicked: settings, next: 'run open-usage again if usage is not visible' };
78
+ return { ok: false, reason: 'usage entry not found' };
79
+ })()`;
80
+ }
81
+
82
+ export function summaryExpression() {
83
+ return `(() => {
84
+ const bodyText = document.body?.innerText || "";
85
+ const buttons = Array.from(document.querySelectorAll('button,[role=button]')).map((el) => {
86
+ const r = el.getBoundingClientRect();
87
+ return {
88
+ text: (el.innerText || el.textContent || el.getAttribute('aria-label') || '').trim().slice(0, 120),
89
+ aria: el.getAttribute('aria-label'),
90
+ disabled: Boolean(el.disabled) || el.getAttribute('aria-disabled') === 'true',
91
+ rect: { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) },
92
+ };
93
+ });
94
+ const visibleButtons = buttons.filter((button) => button.rect.w > 0 && button.rect.h > 0);
95
+ return {
96
+ running: /\\bWorking for\\b/.test(bodyText) || visibleButtons.some((button) => button.text === 'Stop' || button.aria === 'Stop'),
97
+ awaitingApproval: /Awaiting approval|Permission required/.test(bodyText),
98
+ workedFor: (bodyText.match(/Worked for\\s+([^\\n]+)/) || [])[1] || null,
99
+ contextUsage: (bodyText.match(/Context usage\\s+[^\\n]+/) || [])[0] || null,
100
+ activeMode: visibleButtons.find((button) => button.aria === 'Switch mode')?.text || null,
101
+ activeModel: visibleButtons.find((button) => button.aria === 'Choose model')?.text || null,
102
+ activeWorkspace: visibleButtons.find((button) => button.aria === 'Choose workspace')?.text || null,
103
+ lastText: bodyText.slice(-3000),
104
+ };
105
+ })()`;
106
+ }
@@ -0,0 +1,135 @@
1
+ const OVERLOAD_RE = /temporarily overloaded|try again later|overloaded_error/i;
2
+
3
+ export const DEFAULT_PROVIDER_MAX_ATTEMPTS = 2;
4
+ export const DEFAULT_PROVIDER_RETRY_DELAY_MS = 60_000;
5
+
6
+ function firstMatch(text, patterns) {
7
+ for (const pattern of patterns) {
8
+ const match = text.match(pattern);
9
+ if (match?.[1]) return match[1];
10
+ }
11
+ return null;
12
+ }
13
+
14
+ function firstProviderLine(text) {
15
+ return text.split(/\r?\n/).find((line) => /ProviderBusinessError|PROVIDER_BUSINESS_ERROR/i.test(line)) ?? null;
16
+ }
17
+
18
+ export function classifyProviderError({ stdout = "", stderr = "", exitCode = null } = {}) {
19
+ const text = `${stderr}\n${stdout}`;
20
+ const exitCodeNumber = Number(exitCode);
21
+ const exit143 = Number.isFinite(exitCodeNumber) && exitCodeNumber === 143;
22
+ const providerBusiness = /ProviderBusinessError|PROVIDER_BUSINESS_ERROR|isProviderBusinessError:\s*true/i.test(text);
23
+ const providerCode = firstMatch(text, [
24
+ /providerCode:\s*['"]?(\d+)['"]?/,
25
+ /"providerCode"\s*:\s*"(\d+)"/,
26
+ /\[(\d{3,})\]\[/,
27
+ /\bcode:\s*['"]?(\d{3,})['"]?/,
28
+ /"code"\s*:\s*"(\d{3,})"/,
29
+ ]);
30
+ const temporary = OVERLOAD_RE.test(text) || providerCode === "1305";
31
+ const providerError = providerBusiness || temporary || providerCode === "1305" || exit143;
32
+ const providerMessage = firstMatch(text, [
33
+ /providerMessage:\s*'([^']+)'/,
34
+ /providerMessage:\s*"([^"]+)"/,
35
+ /"providerMessage"\s*:\s*"([^"]+)"/,
36
+ /ProviderBusinessError:\s*([^\n]+)/,
37
+ ]) ?? (exit143 ? "ZCode CLI exited with code 143" : null);
38
+
39
+ return {
40
+ provider_error: providerError,
41
+ provider_code: providerCode,
42
+ provider_message: providerMessage,
43
+ provider_id: firstMatch(text, [/providerId:\s*'([^']+)'/, /providerId:\s*"([^"]+)"/, /"providerId"\s*:\s*"([^"]+)"/]),
44
+ provider_kind: firstMatch(text, [/providerKind:\s*'([^']+)'/, /providerKind:\s*"([^"]+)"/, /"providerKind"\s*:\s*"([^"]+)"/]),
45
+ provider_request_id: firstMatch(text, [
46
+ /providerRequestId:\s*'([^']+)'/,
47
+ /providerRequestId:\s*"([^"]+)"/,
48
+ /"providerRequestId"\s*:\s*"([^"]+)"/,
49
+ /request_id:\s*'([^']+)'/,
50
+ /"request_id"\s*:\s*"([^"]+)"/,
51
+ ]),
52
+ provider_error_line: firstProviderLine(text),
53
+ provider_error_temporary: temporary,
54
+ retryable_provider_error: providerError && (temporary || exit143),
55
+ };
56
+ }
57
+
58
+ function parsedJsonObjects(stdout) {
59
+ const trimmed = stdout.trim();
60
+ if (!trimmed) return [];
61
+ const candidates = [trimmed, ...trimmed.split(/\r?\n/).filter((line) => line.trim().startsWith("{"))];
62
+ const objects = [];
63
+ for (const candidate of candidates) {
64
+ try {
65
+ const parsed = JSON.parse(candidate);
66
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) objects.push(parsed);
67
+ } catch {
68
+ // CLI output may be prose, JSONL, or empty; non-JSON chunks are ignored.
69
+ }
70
+ }
71
+ return objects;
72
+ }
73
+
74
+ function hasUsageShape(value) {
75
+ if (!value || typeof value !== "object") return false;
76
+ const usage = value.usage;
77
+ if (usage && typeof usage === "object") return true;
78
+ return [
79
+ "tokens_total",
80
+ "total_tokens",
81
+ "input_tokens",
82
+ "output_tokens",
83
+ "cache_read_tokens",
84
+ ].some((key) => typeof value[key] === "number");
85
+ }
86
+
87
+ export function usageAvailableFromStdout(stdout = "") {
88
+ return parsedJsonObjects(stdout).some(hasUsageShape);
89
+ }
90
+
91
+ export function classifyProviderRunState({ cliOk, provider, audit }) {
92
+ if (cliOk) {
93
+ if (audit?.ok === false) {
94
+ const changedCount = Number.isFinite(Number(audit?.changed_count)) ? Number(audit.changed_count) : null;
95
+ return {
96
+ supervisor_state: "audit_failed",
97
+ partial_artifacts_possible: changedCount === null ? true : changedCount > 0,
98
+ safe_to_retry_later: false,
99
+ };
100
+ }
101
+ return {
102
+ supervisor_state: "success",
103
+ partial_artifacts_possible: false,
104
+ safe_to_retry_later: false,
105
+ };
106
+ }
107
+ if (!provider?.provider_error) {
108
+ return {
109
+ supervisor_state: "cli_error",
110
+ partial_artifacts_possible: false,
111
+ safe_to_retry_later: false,
112
+ };
113
+ }
114
+
115
+ const changedCount = Number.isFinite(Number(audit?.changed_count)) ? Number(audit.changed_count) : null;
116
+ if (changedCount === 0 && provider.retryable_provider_error) {
117
+ return {
118
+ supervisor_state: "retryable_provider_error",
119
+ partial_artifacts_possible: false,
120
+ safe_to_retry_later: true,
121
+ };
122
+ }
123
+ if (changedCount !== null && changedCount > 0 && audit?.ok === true) {
124
+ return {
125
+ supervisor_state: "partial_success",
126
+ partial_artifacts_possible: true,
127
+ safe_to_retry_later: false,
128
+ };
129
+ }
130
+ return {
131
+ supervisor_state: "unsafe_partial",
132
+ partial_artifacts_possible: changedCount === null ? true : changedCount > 0,
133
+ safe_to_retry_later: false,
134
+ };
135
+ }