@orkestrel/scaffold 0.0.1
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/LICENSE +21 -0
- package/README.md +114 -0
- package/dist/bin/scaffold.js +1539 -0
- package/dist/bin/scaffold.js.map +1 -0
- package/dist/host/AGENTS.md +939 -0
- package/dist/host/CLAUDE.md +495 -0
- package/dist/host/LICENSE +21 -0
- package/dist/host/claude/agents/builder.md +48 -0
- package/dist/host/claude/agents/checker.md +37 -0
- package/dist/host/claude/agents/composer.md +64 -0
- package/dist/host/claude/agents/grok.md +50 -0
- package/dist/host/claude/agents/orkestrel.md +236 -0
- package/dist/host/claude/agents/planner.md +44 -0
- package/dist/host/claude/agents/researcher.md +38 -0
- package/dist/host/claude/agents/reviewer.md +47 -0
- package/dist/host/claude/agents/scout.md +35 -0
- package/dist/host/claude/agents/verifier.md +34 -0
- package/dist/host/claude/settings.json +26 -0
- package/dist/host/dotfiles/editorconfig +17 -0
- package/dist/host/dotfiles/gitattributes +3 -0
- package/dist/host/dotfiles/gitignore +40 -0
- package/dist/host/dotfiles/oxfmtrc.json +18 -0
- package/dist/host/dotfiles/oxlintignore +20 -0
- package/dist/host/dotfiles/oxlintrc.json +58 -0
- package/dist/host/dotfiles/prettierignore +5 -0
- package/dist/host/github/workflows/ci.yml +64 -0
- package/dist/host/guides/src/guide.md +312 -0
- package/dist/host/guides/src/scaffold.md +2152 -0
- package/dist/host/manifest.json +137 -0
- package/dist/host/scripts/cursor.sh +74 -0
- package/dist/host/scripts/deps.sh +38 -0
- package/dist/host/scripts/ollama.sh +163 -0
- package/dist/src/core/index.cjs +3728 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +1941 -0
- package/dist/src/core/index.d.ts +1941 -0
- package/dist/src/core/index.js +3636 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/server/index.cjs +1595 -0
- package/dist/src/server/index.cjs.map +1 -0
- package/dist/src/server/index.d.cts +779 -0
- package/dist/src/server/index.d.ts +779 -0
- package/dist/src/server/index.js +1572 -0
- package/dist/src/server/index.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"storage": "claude/agents/builder.md",
|
|
4
|
+
"destination": ".claude/agents/builder.md",
|
|
5
|
+
"executable": false
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"storage": "claude/agents/checker.md",
|
|
9
|
+
"destination": ".claude/agents/checker.md",
|
|
10
|
+
"executable": false
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"storage": "claude/agents/composer.md",
|
|
14
|
+
"destination": ".claude/agents/composer.md",
|
|
15
|
+
"executable": false
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"storage": "claude/agents/grok.md",
|
|
19
|
+
"destination": ".claude/agents/grok.md",
|
|
20
|
+
"executable": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"storage": "claude/agents/orkestrel.md",
|
|
24
|
+
"destination": ".claude/agents/orkestrel.md",
|
|
25
|
+
"executable": false
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"storage": "claude/agents/planner.md",
|
|
29
|
+
"destination": ".claude/agents/planner.md",
|
|
30
|
+
"executable": false
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"storage": "claude/agents/researcher.md",
|
|
34
|
+
"destination": ".claude/agents/researcher.md",
|
|
35
|
+
"executable": false
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"storage": "claude/agents/reviewer.md",
|
|
39
|
+
"destination": ".claude/agents/reviewer.md",
|
|
40
|
+
"executable": false
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"storage": "claude/agents/scout.md",
|
|
44
|
+
"destination": ".claude/agents/scout.md",
|
|
45
|
+
"executable": false
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"storage": "claude/agents/verifier.md",
|
|
49
|
+
"destination": ".claude/agents/verifier.md",
|
|
50
|
+
"executable": false
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"storage": "claude/settings.json",
|
|
54
|
+
"destination": ".claude/settings.json",
|
|
55
|
+
"executable": false
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"storage": "dotfiles/editorconfig",
|
|
59
|
+
"destination": ".editorconfig",
|
|
60
|
+
"executable": false
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"storage": "dotfiles/gitattributes",
|
|
64
|
+
"destination": ".gitattributes",
|
|
65
|
+
"executable": false
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"storage": "github/workflows/ci.yml",
|
|
69
|
+
"destination": ".github/workflows/ci.yml",
|
|
70
|
+
"executable": false
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"storage": "dotfiles/gitignore",
|
|
74
|
+
"destination": ".gitignore",
|
|
75
|
+
"executable": false
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"storage": "dotfiles/oxfmtrc.json",
|
|
79
|
+
"destination": ".oxfmtrc.json",
|
|
80
|
+
"executable": false
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"storage": "dotfiles/oxlintignore",
|
|
84
|
+
"destination": ".oxlintignore",
|
|
85
|
+
"executable": false
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"storage": "dotfiles/oxlintrc.json",
|
|
89
|
+
"destination": ".oxlintrc.json",
|
|
90
|
+
"executable": false
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"storage": "dotfiles/prettierignore",
|
|
94
|
+
"destination": ".prettierignore",
|
|
95
|
+
"executable": false
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"storage": "AGENTS.md",
|
|
99
|
+
"destination": "AGENTS.md",
|
|
100
|
+
"executable": false
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"storage": "CLAUDE.md",
|
|
104
|
+
"destination": "CLAUDE.md",
|
|
105
|
+
"executable": false
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"storage": "LICENSE",
|
|
109
|
+
"destination": "LICENSE",
|
|
110
|
+
"executable": false
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"storage": "guides/src/guide.md",
|
|
114
|
+
"destination": "guides/src/guide.md",
|
|
115
|
+
"executable": false
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"storage": "guides/src/scaffold.md",
|
|
119
|
+
"destination": "guides/src/scaffold.md",
|
|
120
|
+
"executable": false
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"storage": "scripts/cursor.sh",
|
|
124
|
+
"destination": "scripts/cursor.sh",
|
|
125
|
+
"executable": true
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"storage": "scripts/deps.sh",
|
|
129
|
+
"destination": "scripts/deps.sh",
|
|
130
|
+
"executable": true
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"storage": "scripts/ollama.sh",
|
|
134
|
+
"destination": "scripts/ollama.sh",
|
|
135
|
+
"executable": true
|
|
136
|
+
}
|
|
137
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# scripts/cursor.sh — SessionStart hook: Cursor bench ONLY
|
|
4
|
+
# ----------------------------------------------------------------------------
|
|
5
|
+
# The Cursor CLI has no daemon to launch: `agent` is invoked on demand by the
|
|
6
|
+
# composer/grok dispatchers. This hook SENSES the bench at session start and
|
|
7
|
+
# announces the result into Claude's context (SessionStart stdout).
|
|
8
|
+
#
|
|
9
|
+
# AUTH SENSING — evidence-based, in order of authority:
|
|
10
|
+
# 1. `agent status` exits 0 even when it prints "Not logged in" — its exit
|
|
11
|
+
# code proves nothing, and under CURSOR_API_KEY auth "Not logged in" is
|
|
12
|
+
# COSMETIC on headless hosts (status reflects interactive login only;
|
|
13
|
+
# key auth here is verified end-to-end and works regardless).
|
|
14
|
+
# 2. The per-session functional signal is `agent models`: reachable + pins
|
|
15
|
+
# present on the account ⇒ the bench is usable. A live dispatch remains
|
|
16
|
+
# the final arbiter; only USER API keys work (admin/org keys fail at
|
|
17
|
+
# dispatch time).
|
|
18
|
+
# NEVER prints CURSOR_API_KEY. Always exits 0 — problems are announcements,
|
|
19
|
+
# not session blockers.
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if ! command -v agent >/dev/null 2>&1; then
|
|
27
|
+
echo "cursor.sh: bench dark — Cursor CLI not installed in this environment; route external-bench units to their Claude counterparts."
|
|
28
|
+
exit 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# --- evidence gathering ------------------------------------------------------
|
|
32
|
+
agent status >/tmp/cursor-status.log 2>&1 || true
|
|
33
|
+
status_line="$(head -n 1 /tmp/cursor-status.log 2>/dev/null)"
|
|
34
|
+
|
|
35
|
+
models_ok=0
|
|
36
|
+
if agent models >/tmp/cursor-models.log 2>&1; then
|
|
37
|
+
models_ok=1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Exact-token match so a pin can't false-positive on a longer variant
|
|
41
|
+
# (e.g. pin "composer-2.5" must not be satisfied by "composer-2.5-fast").
|
|
42
|
+
id_ok() {
|
|
43
|
+
esc="$(printf '%s' "$1" | sed 's/[][\.^$*+?(){}|]/\\&/g')"
|
|
44
|
+
grep -Eq "${esc}([^A-Za-z0-9._-]|$)" /tmp/cursor-models.log
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# --- pins verdict ------------------------------------------------------------
|
|
48
|
+
pins="pins ok (composer=${CURSOR_COMPOSER_MODEL:-}, grok=${CURSOR_GROK_MODEL:-})"
|
|
49
|
+
if [ -z "${CURSOR_COMPOSER_MODEL:-}" ] || [ -z "${CURSOR_GROK_MODEL:-}" ]; then
|
|
50
|
+
pins="PINS MISSING — run \`agent models\` and record CURSOR_COMPOSER_MODEL / CURSOR_GROK_MODEL in the environment variables"
|
|
51
|
+
elif [ "$models_ok" = "1" ]; then
|
|
52
|
+
for id in "$CURSOR_COMPOSER_MODEL" "$CURSOR_GROK_MODEL"; do
|
|
53
|
+
if ! id_ok "$id"; then
|
|
54
|
+
pins="PIN NOT FOUND on this account: ${id} — re-run \`agent models\` and update the environment variable"
|
|
55
|
+
break
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
else
|
|
59
|
+
pins="pins set (composer=${CURSOR_COMPOSER_MODEL}, grok=${CURSOR_GROK_MODEL}) — unvalidated (\`agent models\` unreachable)"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# --- auth verdict: functional evidence over status text ----------------------
|
|
63
|
+
if [ -s /tmp/cursor-status.log ] && ! grep -qi "not logged in" /tmp/cursor-status.log; then
|
|
64
|
+
auth="interactive login present (${status_line})"
|
|
65
|
+
elif [ -z "${CURSOR_API_KEY:-}" ]; then
|
|
66
|
+
auth="AUTH DARK — no interactive login and no CURSOR_API_KEY set; add a USER API key in the environment settings"
|
|
67
|
+
elif [ "$models_ok" = "1" ]; then
|
|
68
|
+
auth="key-auth reachable (status 'Not logged in' is cosmetic under key auth)"
|
|
69
|
+
else
|
|
70
|
+
auth="key-auth UNVERIFIED — \`agent models\` unreachable (auth or network; see /tmp/cursor-models.log); if dispatches auth-fail, confirm the key is a USER API key, not admin"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
echo "cursor.sh: bench lit — $(agent --version 2>/dev/null | head -n 1); ${auth}; ${pins}."
|
|
74
|
+
exit 0
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# scripts/deps.sh — SessionStart hook: project dependencies ONLY
|
|
4
|
+
# ----------------------------------------------------------------------------
|
|
5
|
+
# Runs in every cloud environment (the setup script never sees the repo
|
|
6
|
+
# checkout; $CLAUDE_PROJECT_DIR here always points at the real one).
|
|
7
|
+
# SessionStart stdout is injected into Claude's context, so this script prints
|
|
8
|
+
# ONE meaningful line and sends the npm noise to /tmp/deps.log.
|
|
9
|
+
# ============================================================================
|
|
10
|
+
|
|
11
|
+
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
cd "$CLAUDE_PROJECT_DIR" || exit 0
|
|
16
|
+
|
|
17
|
+
if [ ! -f package.json ]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
if [ -d node_modules ]; then
|
|
21
|
+
echo "deps.sh: dependencies already present (resumed session) — skipped."
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
if [ -f package-lock.json ]; then
|
|
26
|
+
if npm ci >/tmp/deps.log 2>&1; then
|
|
27
|
+
echo "deps.sh: dependencies installed (npm ci)."
|
|
28
|
+
else
|
|
29
|
+
echo "deps.sh: npm ci FAILED — see /tmp/deps.log before building or testing."
|
|
30
|
+
fi
|
|
31
|
+
else
|
|
32
|
+
if npm install >/tmp/deps.log 2>&1; then
|
|
33
|
+
echo "deps.sh: no package-lock.json — npm install succeeded. Commit a lockfile for reproducible installs."
|
|
34
|
+
else
|
|
35
|
+
echo "deps.sh: npm install FAILED — see /tmp/deps.log before building or testing."
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
exit 0
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# scripts/ollama.sh — SessionStart hook: Ollama ONLY
|
|
4
|
+
# ----------------------------------------------------------------------------
|
|
5
|
+
# One job: bring the local-model daemon up for this session, healthy.
|
|
6
|
+
# Project dependencies live in scripts/deps.sh; the Cursor bench check lives in
|
|
7
|
+
# scripts/cursor.sh. All three are registered in .claude/settings.json and run
|
|
8
|
+
# IN PARALLEL at session start, so the daemon boots while npm installs.
|
|
9
|
+
#
|
|
10
|
+
# 0. Guards -- the orchestration set (hooks included) is mirrored
|
|
11
|
+
# byte-identical across every @orkestrel repo, and this repo serves
|
|
12
|
+
# several cloud environments: exit quietly in any repo that isn't
|
|
13
|
+
# @orkestrel/ollama, and wherever the ollama binary isn't installed.
|
|
14
|
+
# 1. Starts `ollama serve` -- the environment cache snapshots FILES, not
|
|
15
|
+
# running processes, so the daemon must be restarted every session.
|
|
16
|
+
# 2. Self-heals a known container defect -- this container class advertises
|
|
17
|
+
# AMX CPU flags but blocks AMX tile-state permissions at the kernel /
|
|
18
|
+
# seccomp level. Ollama's dynamic CPU-backend loader picks its only
|
|
19
|
+
# AMX-capable variant (libggml-cpu-sapphirerapids.so) on such hosts, and
|
|
20
|
+
# llama-server then segfaults on every model load. A cheap chat probe
|
|
21
|
+
# after the daemon comes up doubles as session warmup AND a canary for
|
|
22
|
+
# this failure; if it fires, we disable that .so and restart the daemon
|
|
23
|
+
# so the loader falls back to the next-best AVX-512 variant.
|
|
24
|
+
#
|
|
25
|
+
# SessionStart stdout is injected into Claude's context: keep stdout to terse
|
|
26
|
+
# status lines (they tell Claude what this environment offers); diagnostics go
|
|
27
|
+
# to stderr / /tmp/ollama.log. No `set -e`: a self-heal misfire should not
|
|
28
|
+
# stop Ollama from coming up.
|
|
29
|
+
# ============================================================================
|
|
30
|
+
|
|
31
|
+
# Run only in cloud sessions. Locally you manage your own Ollama, so skip.
|
|
32
|
+
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# --- 0. Guards ---------------------------------------------------------------
|
|
37
|
+
# The daemon only serves the ollama package; every other @orkestrel repo
|
|
38
|
+
# carries this script as part of the mirrored hook set and must skip silently.
|
|
39
|
+
PKG_JSON="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}/package.json"
|
|
40
|
+
if ! grep -Eq '"name"[[:space:]]*:[[:space:]]*"@orkestrel/ollama"' "$PKG_JSON" 2>/dev/null; then
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
if ! command -v ollama >/dev/null 2>&1; then
|
|
44
|
+
echo "ollama.sh: ollama not installed in this environment — no local model daemon."
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Match the locations used by the setup script / environment variables.
|
|
49
|
+
export OLLAMA_MODELS="${OLLAMA_MODELS:-/opt/ollama/models}"
|
|
50
|
+
export OLLAMA_HOST="${OLLAMA_HOST:-127.0.0.1:11434}"
|
|
51
|
+
|
|
52
|
+
# Your Copilot workflow set OLLAMA_ORIGINS="*" so browser page contexts could
|
|
53
|
+
# call the API cross-origin. That was mainly a Playwright concern, so it is off
|
|
54
|
+
# here. Uncomment if anything still hits Ollama from a browser:
|
|
55
|
+
# export OLLAMA_ORIGINS="*"
|
|
56
|
+
|
|
57
|
+
# --- 1. Start the daemon ----------------------------------------------------
|
|
58
|
+
if ! curl -sf "http://${OLLAMA_HOST}/api/tags" >/dev/null 2>&1; then
|
|
59
|
+
nohup ollama serve >/tmp/ollama.log 2>&1 &
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
ollama_ready=0
|
|
63
|
+
for i in $(seq 1 30); do
|
|
64
|
+
if curl -sf "http://${OLLAMA_HOST}/api/tags" >/dev/null 2>&1; then
|
|
65
|
+
echo "Ollama ready on ${OLLAMA_HOST}"
|
|
66
|
+
ollama_ready=1
|
|
67
|
+
break
|
|
68
|
+
fi
|
|
69
|
+
sleep 1
|
|
70
|
+
done
|
|
71
|
+
|
|
72
|
+
if [ "$ollama_ready" != "1" ]; then
|
|
73
|
+
# Don't fail the session if the daemon is slow; Claude can retry mid-session.
|
|
74
|
+
echo "Warning: Ollama did not report ready within 30s (see /tmp/ollama.log)" >&2
|
|
75
|
+
exit 0
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# --- 2. Self-heal the AMX/XTILE-blocked-container defect --------------------
|
|
79
|
+
# See header note 2. A minimal chat call against whatever model is already
|
|
80
|
+
# installed both warms that model for the session AND tells us whether this
|
|
81
|
+
# container hit the AMX-tile-permission wall. If it did, disable the
|
|
82
|
+
# AMX-only CPU backend variant and restart the daemon so the loader falls
|
|
83
|
+
# back to AVX-512, then re-probe once to confirm the fix landed.
|
|
84
|
+
sapphirerapids_so="/usr/local/lib/ollama/libggml-cpu-sapphirerapids.so"
|
|
85
|
+
|
|
86
|
+
probe_model() {
|
|
87
|
+
curl -sf "http://${OLLAMA_HOST}/api/tags" 2>/dev/null \
|
|
88
|
+
| grep -o '"name":"[^"]*"' \
|
|
89
|
+
| head -n 1 \
|
|
90
|
+
| sed -e 's/"name":"//' -e 's/"$//'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
probe_chat() {
|
|
94
|
+
model="$1"
|
|
95
|
+
curl -s --max-time 120 "http://${OLLAMA_HOST}/api/chat" \
|
|
96
|
+
-d "{\"model\":\"${model}\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"stream\":false,\"think\":false,\"keep_alive\":\"30m\",\"options\":{\"num_predict\":1}}"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
model="$(probe_model)"
|
|
100
|
+
if [ -z "$model" ]; then
|
|
101
|
+
# No model installed yet -- nothing to warm or probe against.
|
|
102
|
+
echo "ollama.sh: no installed model found, skipping warmup probe." >&2
|
|
103
|
+
exit 0
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
probe_response="$(probe_chat "$model")"
|
|
107
|
+
|
|
108
|
+
if echo "$probe_response" | grep -qi 'segmentation fault\|llama-server process has terminated'; then
|
|
109
|
+
echo "ollama.sh: detected llama-server crash on model warmup (likely the AMX/XTILE-blocked-container defect)." >&2
|
|
110
|
+
if [ -f "$sapphirerapids_so" ]; then
|
|
111
|
+
echo "ollama.sh: disabling AMX-only CPU backend variant so the loader falls back to AVX-512." >&2
|
|
112
|
+
if mv "$sapphirerapids_so" "${sapphirerapids_so}.disabled" 2>/dev/null; then
|
|
113
|
+
echo "ollama.sh: restarting Ollama daemon to pick up the backend change." >&2
|
|
114
|
+
ollama_pid="$(pgrep -x ollama | head -n 1)"
|
|
115
|
+
if [ -n "$ollama_pid" ]; then
|
|
116
|
+
kill "$ollama_pid" 2>/dev/null
|
|
117
|
+
# Wait for the old process to actually exit before relaunching, so the
|
|
118
|
+
# new daemon can't race the dying one for the port and the readiness
|
|
119
|
+
# poll below can't be satisfied by the dying daemon.
|
|
120
|
+
for i in $(seq 1 10); do
|
|
121
|
+
if ! kill -0 "$ollama_pid" 2>/dev/null; then
|
|
122
|
+
break
|
|
123
|
+
fi
|
|
124
|
+
sleep 0.5
|
|
125
|
+
done
|
|
126
|
+
fi
|
|
127
|
+
nohup ollama serve >/tmp/ollama.log 2>&1 &
|
|
128
|
+
|
|
129
|
+
restarted_ready=0
|
|
130
|
+
for i in $(seq 1 30); do
|
|
131
|
+
if curl -sf "http://${OLLAMA_HOST}/api/tags" >/dev/null 2>&1; then
|
|
132
|
+
restarted_ready=1
|
|
133
|
+
break
|
|
134
|
+
fi
|
|
135
|
+
sleep 1
|
|
136
|
+
done
|
|
137
|
+
|
|
138
|
+
if [ "$restarted_ready" = "1" ]; then
|
|
139
|
+
retry_response="$(probe_chat "$model")"
|
|
140
|
+
if echo "$retry_response" | grep -qi 'segmentation fault\|llama-server process has terminated'; then
|
|
141
|
+
echo "ollama.sh: self-heal restart complete, but the retry probe still failed. See /tmp/ollama.log." >&2
|
|
142
|
+
else
|
|
143
|
+
echo "ollama.sh: self-heal succeeded -- model warm (${model}) after AVX-512 fallback."
|
|
144
|
+
fi
|
|
145
|
+
else
|
|
146
|
+
echo "ollama.sh: daemon did not report ready after self-heal restart (see /tmp/ollama.log)." >&2
|
|
147
|
+
fi
|
|
148
|
+
else
|
|
149
|
+
echo "ollama.sh: warning -- could not rename ${sapphirerapids_so} (permissions?). Leaving daemon as-is." >&2
|
|
150
|
+
fi
|
|
151
|
+
else
|
|
152
|
+
echo "ollama.sh: warning -- AMX-only CPU backend not found at expected path; cannot self-heal automatically." >&2
|
|
153
|
+
fi
|
|
154
|
+
elif echo "$probe_response" | grep -q '"message"\|"content"\|"done":true'; then
|
|
155
|
+
echo "ollama.sh: model warm (${model}) -- warmup probe succeeded."
|
|
156
|
+
else
|
|
157
|
+
echo "ollama.sh: warning -- warmup probe returned an unexpected response (not a segfault, but no message/done payload either):" >&2
|
|
158
|
+
echo "ollama.sh: ${probe_response}" | head -c 500 >&2
|
|
159
|
+
echo "" >&2
|
|
160
|
+
echo "ollama.sh: leaving daemon as-is." >&2
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
exit 0
|