shraga 0.1.41 → 0.1.43
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shraga",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.43",
|
|
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",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"express": "^4.21.1",
|
|
71
71
|
"firebase": "^11.0.0",
|
|
72
72
|
"lucide-react": "^0.468.0",
|
|
73
|
-
"mcp-slack-use": "github:Livshitz/mcp-slack-use#
|
|
73
|
+
"mcp-slack-use": "github:Livshitz/mcp-slack-use#38ff8b7",
|
|
74
74
|
"react": "^19.0.0",
|
|
75
75
|
"react-dom": "^19.0.0",
|
|
76
76
|
"react-markdown": "^9.0.0",
|
|
@@ -19,6 +19,7 @@ const IMMUTABLE_SYSTEM_PROMPT = readFileSync(path.resolve(import.meta.dirname, '
|
|
|
19
19
|
const DEFAULT_USER_PROMPT = `You are a helpful assistant with access to MCP tools.`;
|
|
20
20
|
const DEFAULT_ALLOWED_TOOLS = ['Read', 'Edit', 'Bash', 'WebSearch', 'Glob', 'LS', 'ToolSearch'];
|
|
21
21
|
const BG_TASK_MAX_WAIT_MS = 15 * 60_000;
|
|
22
|
+
const BG_HEARTBEAT_MS = 60_000;
|
|
22
23
|
const HISTORY_LIMIT = 50;
|
|
23
24
|
|
|
24
25
|
const NO_INTERACTIVE_ANSWER = 'No interactive channel is available to answer right now. Use your best judgement to proceed, and surface these options to the user in your reply so they can redirect if needed.';
|
|
@@ -313,7 +314,8 @@ export class ClaudeCodeEngine implements AgentEngine {
|
|
|
313
314
|
let waitingForBg = false;
|
|
314
315
|
let bgTimer: Promise<'__bgtimeout'> | null = null;
|
|
315
316
|
let bgTimerHandle: ReturnType<typeof setTimeout> | null = null;
|
|
316
|
-
|
|
317
|
+
let bgHeartbeat: ReturnType<typeof setInterval> | null = null;
|
|
318
|
+
const clearBgTimer = () => { if (bgTimerHandle) { clearTimeout(bgTimerHandle); bgTimerHandle = null; } bgTimer = null; if (bgHeartbeat) { clearInterval(bgHeartbeat); bgHeartbeat = null; } };
|
|
317
319
|
|
|
318
320
|
try {
|
|
319
321
|
while (true) {
|
|
@@ -395,7 +397,14 @@ export class ClaudeCodeEngine implements AgentEngine {
|
|
|
395
397
|
console.log(`[claude] Result: subtype=${m.subtype}→${sub} session=${lastSessionId} turns=${sdkTurns}/${maxTurns} cost=$${m.total_cost_usd?.toFixed(4) ?? '?'} msgs=${messageCount} deltas=${textDeltaCount} (${elapsed()})`);
|
|
396
398
|
logCacheUsage(m.usage, activeModel);
|
|
397
399
|
if (outstandingTasks.size > 0) {
|
|
398
|
-
if (!waitingForBg) {
|
|
400
|
+
if (!waitingForBg) {
|
|
401
|
+
waitingForBg = true; clearBgTimer();
|
|
402
|
+
console.log(`[claude] Holding stream for ${outstandingTasks.size} bg tasks (${elapsed()})`);
|
|
403
|
+
// The hold is invisible to the user (their next message queues behind it), so beat
|
|
404
|
+
// every minute — otherwise a stuck task reads as a dead agent with nothing in the log.
|
|
405
|
+
bgHeartbeat = setInterval(() => console.log(`[claude] Still holding for ${outstandingTasks.size} bg task(s): ${[...outstandingTasks].join(',')} (${elapsed()})`), BG_HEARTBEAT_MS);
|
|
406
|
+
bgHeartbeat.unref?.();
|
|
407
|
+
}
|
|
399
408
|
continue;
|
|
400
409
|
}
|
|
401
410
|
// The SDK reports `subtype: 'success'` even when the API call failed (e.g. an org spend
|
|
@@ -27,6 +27,24 @@ BUN="${BUN:-bun}"
|
|
|
27
27
|
BOOT_TIMEOUT="${BOOT_TIMEOUT:-180}"
|
|
28
28
|
SOAK="${SOAK:-60}"
|
|
29
29
|
|
|
30
|
+
# ── Escape the service cgroup ─────────────────────────────────────────────────
|
|
31
|
+
# Under systemd the default KillMode=control-group kills EVERY process in the unit's cgroup on
|
|
32
|
+
# restart — and a detached child of the server is in that cgroup. So the supervisor would be killed
|
|
33
|
+
# by the very restart it triggers, taking the verify AND the rollback with it: exactly the guarantees
|
|
34
|
+
# it exists to provide. Re-exec into a transient scope (same uid, so `bun install` doesn't leave
|
|
35
|
+
# root-owned files) and we live outside the unit. Best-effort: where systemd-run or passwordless sudo
|
|
36
|
+
# is absent, carry on in-cgroup — an unsupervised upgrade still beats no upgrade.
|
|
37
|
+
if [ -z "${UPGRADE_DETACHED:-}" ]; then
|
|
38
|
+
export UPGRADE_DETACHED=1
|
|
39
|
+
if command -v systemd-run >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then
|
|
40
|
+
escape=(sudo -n systemd-run --scope --quiet --collect --uid="$(id -u)" --gid="$(id -g)")
|
|
41
|
+
for v in APP_ROOT PKG TARGET FROM RESTART_CMD HEALTH_URL REPORT BUN BOOT_TIMEOUT SOAK PATH UPGRADE_DETACHED; do
|
|
42
|
+
escape+=("--setenv=$v=${!v-}")
|
|
43
|
+
done
|
|
44
|
+
exec "${escape[@]}" bash "$0"
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
30
48
|
cd "$APP_ROOT" || exit 1
|
|
31
49
|
BACKUP="$(mktemp -d)"
|
|
32
50
|
LOG="${REPORT%.json}.log"
|