shraga 0.1.127 → 0.1.129
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/client/assets/{index-_XEpjgJO.css → index-BLAQpfJ9.css} +1 -1
- package/dist/client/assets/{index-DRTvNKXl.js → index-kSoIKs9H.js} +86 -86
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/src/client/components/ClaudeAccountSection.tsx +30 -24
- package/src/client/components/MachineStats.tsx +4 -2
- package/src/server/data-sync.ts +8 -1
package/dist/client/index.html
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
14
14
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
15
15
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet" />
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-kSoIKs9H.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BLAQpfJ9.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shraga",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.129",
|
|
4
4
|
"description": "The teammate you delegate coding to — a self-hostable, multi-user AI coding agent web UI (Claude Code, with a pluggable engine seam).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -54,35 +54,41 @@ export function ClaudeAccountSection({ getToken }: { getToken: () => Promise<str
|
|
|
54
54
|
? !accounts?.me?.connected || !!accounts.me.useShared
|
|
55
55
|
: !!accounts?.me?.connected && !accounts.me.useShared;
|
|
56
56
|
|
|
57
|
-
const row = (target: Target, title: string, s: AccountStatus | null, canManage = true) =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
const row = (target: Target, title: string, s: AccountStatus | null, canManage = true) => {
|
|
58
|
+
const usage = accounts?.usage?.[target] ?? null;
|
|
59
|
+
const identity = s?.connected ? [s.account ?? 'Connected', s.subscriptionType].filter(Boolean).join(' · ')
|
|
60
|
+
: target === 'me' ? 'Not connected' : canManage ? 'Not connected' : null;
|
|
61
|
+
return (
|
|
62
|
+
<div className="flex items-center justify-between gap-3">
|
|
63
|
+
<div className="min-w-0 space-y-0.5">
|
|
64
|
+
<div className="flex items-center gap-2 text-sm font-medium">
|
|
65
|
+
{title}
|
|
66
|
+
{active(target) && <span className="rounded-full bg-emerald-500/15 px-1.5 py-px text-[10px] font-medium text-emerald-500">Active</span>}
|
|
67
|
+
</div>
|
|
68
|
+
<div className="flex items-center gap-1.5 text-xs text-muted-foreground min-w-0">
|
|
69
|
+
{identity && <span className="truncate">{identity}</span>}
|
|
70
|
+
{identity && usage && <span aria-hidden>·</span>}
|
|
71
|
+
<UsageMetric usage={usage} compact />
|
|
72
|
+
</div>
|
|
67
73
|
</div>
|
|
74
|
+
{canManage && (
|
|
75
|
+
<div className="flex shrink-0 gap-2">
|
|
76
|
+
{target === 'me' && s?.connected && (
|
|
77
|
+
<>
|
|
78
|
+
<Button size="sm" variant="outline" disabled={busy} onClick={() => useShared(!s.useShared)}>{s.useShared ? 'Use mine' : 'Use shared'}</Button>
|
|
79
|
+
<Button size="sm" variant="outline" disabled={busy} onClick={() => disconnect(target)}>Sign out</Button>
|
|
80
|
+
</>
|
|
81
|
+
)}
|
|
82
|
+
<Button size="sm" variant="outline" disabled={busy} onClick={() => connect(target)}>{s?.connected ? 'Replace' : 'Connect'}</Button>
|
|
83
|
+
</div>
|
|
84
|
+
)}
|
|
68
85
|
</div>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
<Button size="sm" variant="outline" disabled={busy} onClick={() => connect(target)}>{s?.connected ? 'Replace' : 'Connect'}</Button>
|
|
72
|
-
{target === 'me' && s?.connected && (
|
|
73
|
-
<>
|
|
74
|
-
<Button size="sm" variant="ghost" disabled={busy} onClick={() => useShared(!s.useShared)}>{s.useShared ? 'Use mine' : 'Use shared'}</Button>
|
|
75
|
-
<Button size="sm" variant="ghost" disabled={busy} onClick={() => disconnect(target)}>Sign out</Button>
|
|
76
|
-
</>
|
|
77
|
-
)}
|
|
78
|
-
</div>
|
|
79
|
-
)}
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
86
|
+
);
|
|
87
|
+
};
|
|
82
88
|
|
|
83
89
|
if (!accounts) return error ? <p className="text-xs text-destructive">{error}</p> : null;
|
|
84
90
|
return (
|
|
85
|
-
<div className="space-y-
|
|
91
|
+
<div className="space-y-4">
|
|
86
92
|
<label className="text-sm font-medium block">Claude subscription</label>
|
|
87
93
|
{accounts.me ? row('me', 'Your subscription', accounts.me) : (
|
|
88
94
|
<p className="text-xs text-muted-foreground">Personal subscription unavailable: you are not a contact on this agent.</p>
|
|
@@ -136,7 +136,7 @@ function ClaudeUsageMetric({ getToken }: { getToken: () => Promise<string | null
|
|
|
136
136
|
|
|
137
137
|
/** Pure render — null usage (204, or any failure) renders NOTHING. Split from the fetching shell so
|
|
138
138
|
* the gate and the labelling are testable without a network or a DOM. */
|
|
139
|
-
export function UsageMetric({ usage }: { usage: Usage | null }) {
|
|
139
|
+
export function UsageMetric({ usage, compact }: { usage: Usage | null; /** Inline text trigger (settings rows) instead of the strip gauge. */ compact?: boolean }) {
|
|
140
140
|
const top = usage && binding(usage.limits);
|
|
141
141
|
const [state, setState] = useState<CardState>(CLOSED);
|
|
142
142
|
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -169,7 +169,9 @@ export function UsageMetric({ usage }: { usage: Usage | null }) {
|
|
|
169
169
|
onPointerEnter={e => send({ type: 'pointerenter', pointerType: e.pointerType }, HOVER_OPEN_MS)}
|
|
170
170
|
onPointerLeave={e => send({ type: 'pointerleave', pointerType: e.pointerType }, HOVER_CLOSE_MS)}
|
|
171
171
|
>
|
|
172
|
-
|
|
172
|
+
{compact
|
|
173
|
+
? <span className={cn('tabular-nums', level(top.percent, top.severity))}>{top.percent}% used</span>
|
|
174
|
+
: <Metric label="usage" value={top.percent} severity={top.severity} />}
|
|
173
175
|
</button>
|
|
174
176
|
</PopoverTrigger>
|
|
175
177
|
<PopoverContent
|
package/src/server/data-sync.ts
CHANGED
|
@@ -85,6 +85,13 @@ export function isChurnPath(file: string): boolean {
|
|
|
85
85
|
|| /\.bak(-|\.|$)/.test(file);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/** Authored documents (HTML reports, dashboards, styles, scripts) are REWRITTEN wholesale by design —
|
|
89
|
+
* a redesign that drops 87 lines is an edit, not data loss (2026-09-17: two trial-journey report
|
|
90
|
+
* copies blocked every flush). The shrink guard protects records like contacts.json, not these. */
|
|
91
|
+
export function isAuthoredDocPath(file: string): boolean {
|
|
92
|
+
return /\.(html?|css|m?[jt]sx?|svg)$/i.test(file);
|
|
93
|
+
}
|
|
94
|
+
|
|
88
95
|
export class DataSyncOptions {
|
|
89
96
|
repoUrl = process.env.DATA_SYNC_REPO || '';
|
|
90
97
|
branch = process.env.DATA_SYNC_BRANCH || 'main';
|
|
@@ -294,7 +301,7 @@ export class DataSync {
|
|
|
294
301
|
const [addRaw, delRaw, file] = line.split('\t');
|
|
295
302
|
if (addRaw === '-' || delRaw === '-' || !file) continue; // binary
|
|
296
303
|
const net = (parseInt(delRaw, 10) || 0) - (parseInt(addRaw, 10) || 0);
|
|
297
|
-
if (net > shrinkThreshold && !isChurnPath(file)) shrunk.push(`• ${file} (−${net} net lines)`);
|
|
304
|
+
if (net > shrinkThreshold && !isChurnPath(file) && !isAuthoredDocPath(file)) shrunk.push(`• ${file} (−${net} net lines)`);
|
|
298
305
|
}
|
|
299
306
|
if (shrunk.length) {
|
|
300
307
|
console.error(`${TAG} 🚫 BLOCKED large content shrink (${context}): ${shrunk.length} file(s) — net-removal threshold is ${shrinkThreshold}`);
|