From 2d0ae9d5e4ccac8146b9f6ef9e154175446acfbc Mon Sep 17 00:00:00 2001 From: Lilith Date: Mon, 5 Jan 2026 15:24:28 -0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20new=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 +++++++-- pyproject.toml | 5 +- .../__pycache__/app.cpython-312.pyc | Bin 17706 -> 17707 bytes .../__pycache__/config.cpython-312.pyc | Bin 4544 -> 5028 bytes .../__pycache__/config.cpython-314.pyc | Bin 4750 -> 5613 bytes src/auto_commit_service/app.py | 2 +- src/auto_commit_service/config.py | 16 +++- .../claude_fallback.cpython-312.pyc | Bin 6246 -> 7851 bytes .../claude_fallback.cpython-314.pyc | Bin 5577 -> 8323 bytes .../recovery/claude_fallback.py | 41 ++++++++- .../__pycache__/daemon.cpython-312.pyc | Bin 29149 -> 29371 bytes .../__pycache__/daemon.cpython-314.pyc | Bin 27456 -> 34386 bytes .../__pycache__/processor.cpython-312.pyc | Bin 14791 -> 16391 bytes .../__pycache__/processor.cpython-314.pyc | Bin 13008 -> 17825 bytes src/auto_commit_service/scheduler/daemon.py | 10 +- .../scheduler/processor.py | 51 +++++++++++ .../__pycache__/manager.cpython-312.pyc | Bin 14460 -> 17937 bytes .../__pycache__/manager.cpython-314.pyc | Bin 0 -> 20917 bytes src/auto_commit_service/service/manager.py | 86 ++++++++++++++++-- 19 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 src/auto_commit_service/service/__pycache__/manager.cpython-314.pyc diff --git a/README.md b/README.md index 3f6695f..5c054ab 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,36 @@ Automated commit message generation service using local LLM inference. Commits a cd /var/home/lilith/Code/@packages/@ml/auto-commit-service pip install -e . +# Or with model-boss integration (recommended) +pip install -e ".[model-boss]" + # Or with dev dependencies pip install -e ".[dev]" ``` +### Model Configuration + +The service requires a language model to generate commit messages. You have three options: + +1. **Auto-load via model-boss (recommended)**: + ```bash + pip install -e ".[model-boss]" + # Models will be auto-downloaded and cached + # Default: ministral-3b-instruct + ``` + +2. **Manual model path**: + ```bash + export LLAMA_SERVICE_FAST_MODEL_PATH=/path/to/model.gguf + ``` + +3. **Disable auto-start** (use external llama-service): + ```bash + export AUTO_COMMIT_LLAMA_SERVICE_AUTOSTART=false + ``` + +**Important**: If no model is configured, the service will fail to start and report as down. This prevents making commits with placeholder messages. + ## Configuration Environment variables (prefix: `AUTO_COMMIT_`): @@ -29,6 +55,9 @@ Environment variables (prefix: `AUTO_COMMIT_`): |----------|---------|-------------| | `AUTO_COMMIT_LLAMA_SERVICE_URL` | `http://localhost:8000` | llama-service URL | | `AUTO_COMMIT_LLAMA_MODEL` | `fast` | Model to use (fast/reasoning) | +| `AUTO_COMMIT_LLAMA_SERVICE_AUTOSTART` | `true` | Auto-start llama-service if down | +| `AUTO_COMMIT_LLAMA_FAST_MODEL_ID` | `ministral-3b-instruct` | Model ID for model-boss | +| `AUTO_COMMIT_USE_MODEL_BOSS` | `true` | Use model-boss for model loading | | `AUTO_COMMIT_CYCLE_INTERVAL_SECONDS` | `900` | Seconds between cycles (15 min) | | `AUTO_COMMIT_ENABLED` | `true` | Enable daemon on startup | | `AUTO_COMMIT_CLAUDE_FALLBACK_ENABLED` | `true` | Enable Claude Code recovery | @@ -109,11 +138,13 @@ Generated commits follow the Lilith Platform convention: ## Error Handling -1. **Push rejected**: Attempts `git pull --rebase` and retries -2. **Merge conflict**: Invokes Claude Code to resolve -3. **Hook failure**: Invokes Claude Code to fix -4. **LLM unavailable**: Skips cycle (logs warning) -5. **Auth failure**: Skips repo (requires manual fix) +1. **No model configured**: Service fails to start, reported as down (prevents bad commits) +2. **Push rejected**: Attempts `git pull --rebase` and retries +3. **Merge conflict**: Invokes Claude Code to resolve +4. **Hook failure**: Invokes Claude Code to fix +5. **LLM unavailable**: Service auto-starts if configured, otherwise skips cycle +6. **Infrastructure errors** (network, auth): Skips Claude recovery, reports error +7. **Auth failure**: Skips repo (requires manual fix) ## Development @@ -152,10 +183,11 @@ auto_commit_service/ ## Dependencies -- `tqftw-ml-service-base`: FastAPI patterns, lifespan, health checks +- `lilith-ml-service-base`: FastAPI patterns, lifespan, health checks - `httpx`: Async HTTP client for llama-service - `pydantic`: Configuration and models - `uvicorn`: ASGI server # Test update Mon Jan 5 12:27:47 PST 2026 # Test change Mon Jan 5 12:43:01 PST 2026 # Test commit hash persistence +Test change Mon Jan 5 15:22:57 PST 2026 diff --git a/pyproject.toml b/pyproject.toml index 92085bd..b503e56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "Automated commit message generation service using local LLM infer readme = "README.md" requires-python = ">=3.11" dependencies = [ - "tqftw-ml-service-base", + "lilith-ml-service-base", "httpx>=0.27.0", "pydantic>=2.0", "pyyaml>=6.0", @@ -13,6 +13,9 @@ dependencies = [ ] [project.optional-dependencies] +model-boss = [ + "lilith-model-boss>=0.1.0", +] dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", diff --git a/src/auto_commit_service/__pycache__/app.cpython-312.pyc b/src/auto_commit_service/__pycache__/app.cpython-312.pyc index cc6a88882beeb9aefd96042e3543ff0a20012921..b40e5c4e3c2522f1ef91784f5cbcb06c690dab7b 100644 GIT binary patch delta 37 rcmZ40#kjhQk@qw&FBbz4Ty&1fl-$Vs%b8s)Co?CrBx5tLi!37m)X)nW delta 36 qcmZ48#ki`Ak@qw&FBbz4nCr)6N^Io)<;*5pQkYg!zM0QOmJtBEL<$-J diff --git a/src/auto_commit_service/__pycache__/config.cpython-312.pyc b/src/auto_commit_service/__pycache__/config.cpython-312.pyc index b527070e18e17fd260f4fffad734f4fabfde9c92..e5745fb27a3365e131e37d8d697ae5d472f6eb76 100644 GIT binary patch delta 660 zcmX@0yhNSvG%qg~0}xzvj>&v0G?8yNlNrm#(=E(GDefsAYgkq@fg~9iqEu7aCg-xq z*0ZIkSFtlNq_U@Y+W^Ix7*bhML{of_RH~;60A+n)vOpDrDSoRN!NxG8_#>&*NEHOC z41lRjQBMg(lGOz2gV_}XQj-##62g(m7^PLIt{J*{DN7@}rf63#Onp&maehu&YKlTxW}-qaNQrJzesQtp zE#aJ;#N5PqkivMdczk9`mA!vKNoIatVh%(p%(SA^#NzzC%)E4klEmWdVg(JHrb<9e zg=>gInC%=|oQmWEg_3*)s4-B>3KB~)iWQPlf$mRLC@x7XDgoIDHc+=XwWusJIrSD_ zX>lslNRT%stMW``)SkSX=QB@{5iq!lj6sCS3xRG&zc_CL0SXvWw+p=46&+OpX$imU0G3gVneKS+_WBfI(ZDlWJGw aIk{g@M%3&Jn=cci(FIAJuM8jtSSbJ%c*DH_ delta 229 zcmZ3Yen6S;G%qg~0}wpZkI6hKFp+OJ(>3Oer(2lim>5z8Q`}cGf+QIjQaskMtY(6+ zqf}D`CnvJVN(-i_SFtlNq_U@Y+kn*gr1)ksMyXe-Yx-?wWo=}iypnecqsC-AzR!~# z`0JTIGi^S|zn*FGK_PcON1*y5pk4+)O^zb-$zsBaY@#KFX(i>8?S!Sh9YC^RB~C!r zEe@O9{FKt1RJ$TKAQ$AKVg(@aftit!@g{@JQwE8<3{rO)Ouw+zGcp=okkt9g0Ahem F006NlI4S@D diff --git a/src/auto_commit_service/__pycache__/config.cpython-314.pyc b/src/auto_commit_service/__pycache__/config.cpython-314.pyc index 11348b5b2f266814dcbcb05f64b0702239d40979..c728a237b8af6fd789f5c77ed13007abcda9484b 100644 GIT binary patch delta 2074 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 U4gY2M@z*U7f;>FOKuP8Q7iI_fEdT%j delta 2722 zcmbtWUu;{|8UN1x>wA6uC${s?acUKv9w4fpe~XV^fAS zX-D#RzVn^${Lc69e#bvg{iWO6?e)k&hFf_uKj**XZQ49XR$HKg0rQ}uX=EUKW(;PY zQJHCWiZi$<%p;YZ=BEThh{72r?WGvs9c^&NHGs-8LsB_IRwb2h1XXB+RsSk7+^R@c zF1j)l6~!STZycPw^!i93fh@0@TP&Q*;R|Z6SXwpS_%y|AP7$yz&|sb!`31ld3lM?F z&(ZCk#%C8%kTngqko9mlHNZtcVZ_A-wmNK8Xy}LYR?h4?o+ZAor1wv>~nls0_ z13&qO2WW>VaUxR*41k85Ak8O7ULbDOQMWYWR8QD37(iuustb4o%_5zxI-2Iqcer{a zP}=OOQLL~U(%7`y{A+zM&Z^u%B|s`aTnUfPWfbRB+DG+xL4&l*+>%1(Sy@qPw(IEj zny7KAtJXk;n3!Z8SEA4YnZQ0|$lVjO^$k~od_U$-i5#ET#I6cTCEa2=?f``!L8@PuG}nD9uBwV`tH{Kt4)ay9 ztHrIk=V4@y6wfhQJT=)WC$p|LnI|$1FldsKFkQ(c9KY0nrl>)URUpZzp zyX_jOufWzn(V)phn{&{jP=nT}Hfi$x#X^vqoe;%Agp=r$UxZU1#cIo@$2>082gj&O z1hHD7<=exv(==ae2 zYtSYrn(nEw`iLE~SjB4lyE^`zFtyEk?2zvVh8n4Qbk8wQyfWue9>&;K$fH3vj}q15^URPitI$XcEWvE z-P_OIY??67)*bA*P35gSP06c6Z+84){A%ybhSXi24S9Eg^>{y@L@vL)*T8nlU)>!t zuh;dV+vZnwNkY2=Lz}mKtvjLSolxhMXRa*X3>+i}{qmQUp-)BA&noOpj|jPTbFQ~r7q zQGU>-!zpEEl>LA`#*m#4co$uG4t2|V;hi0iV`WW)2ahN1wk6m{R2KK&CbFQ_Kso^T#jotc_Fnutk0PDX7(e{@ zApo7#P`c77h~oZuqMyh)Fy9RYHY?jYr*TdPS|+jx%#hYYT4{|p&iVQM$Famj$p9C0-?x7amOEcNxCFm?%GcNZsN6xTmI3D{J-4(=LdI!O)rgI z8oT_AdGtf2ZBHcHdon0~>>DLW36$?4*-dyXabaPpu(+^*yNTEmR}0I_`SoRsUCtZj z|2(dh?E2Db4i_iuvA*j9mS84eOf}r5khuZ zgwWri|6}m}1H7L?ev!?1z&`_2~GDp=s%`==NM9yHuASI C3-%NM diff --git a/src/auto_commit_service/recovery/claude_fallback.py b/src/auto_commit_service/recovery/claude_fallback.py index 7d11027..f68a91d 100644 --- a/src/auto_commit_service/recovery/claude_fallback.py +++ b/src/auto_commit_service/recovery/claude_fallback.py @@ -84,13 +84,14 @@ async def invoke_claude_for_recovery( if returncode == 0: logger.info(f"Claude recovery succeeded for {repo.name}") - # Get the latest commit hash directly from git + # Get the latest commit info directly from git commit_hash = await _get_latest_commit_hash(repo) + commit_message = await _get_latest_commit_message(repo) if commit_hash else None return RecoveryResult( success=True, commit_hash=commit_hash, - message=f"Recovered by Claude: {short_error}", + message=commit_message or f"Recovered by Claude: {short_error}", ) else: logger.error(f"Claude recovery failed for {repo.name}: {stderr}") @@ -155,3 +156,39 @@ async def _get_latest_commit_hash(repo: "Repository") -> str | None: logger.warning(f"Failed to get commit hash from {repo.name}: {e}") return None + + +async def _get_latest_commit_message(repo: "Repository") -> str | None: + """Get the latest commit message (subject line) from the repository. + + Args: + repo: Repository to query + + Returns: + Latest commit message or None if failed + """ + try: + proc = await asyncio.create_subprocess_exec( + "git", + "log", + "-1", + "--format=%s", + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + cwd=str(repo.path), + ) + + stdout_bytes, _ = await asyncio.wait_for( + proc.communicate(), + timeout=5, + ) + + if proc.returncode == 0 and stdout_bytes: + commit_message = stdout_bytes.decode().strip() + logger.debug(f"Got commit message '{commit_message[:50]}...' from {repo.name}") + return commit_message + + except Exception as e: + logger.warning(f"Failed to get commit message from {repo.name}: {e}") + + return None diff --git a/src/auto_commit_service/scheduler/__pycache__/daemon.cpython-312.pyc b/src/auto_commit_service/scheduler/__pycache__/daemon.cpython-312.pyc index 1dee02a288ad8ff84753913a6b9a188d702eecd3..a83d53a365a700292d98074130cc2db21218c6f2 100644 GIT binary patch delta 3644 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 delta 3555 zcmZ`*4RBLg70ylinxubeN+@j;O8P@-+E79ZWr4QzCn-gsUDK9DEIb~`qfJTj%6&=M zcEPgl>HxFrmbtFFqQZ_ljtsjfK7VFs9mg3*9YdG*g3ODz-=qFKbcDi5!ge^E_T8?Myl9ftQWP{avl=W z!oHIy=H1WDt}Zy^znO(g@eS; zZWWbk6NOVj4E{kD#EHOe4Al0NMsGdvZsFc8!ghKm) zOtB{D0Ky;wZmXN($_cs=r`)l1oEDYi9)WwO=Pa0+GQJOa!Gj`$inW7w&l}#uDvRsM z3D#TubMW5YUaB>(a*)EED8P5X4e23vprpPSgQ1(jz%f-0t46MfcCrg4ZR9zommCHK z(`DOOvb5H|1*LWaq$AC)me!Vj9tiia4o@5AvJHif=T4nHHDhtnl$@um%D#1(+`+Qi z+>1z!ARy;{`}SpA56WttF9B7>lAhOo!?tGDwr0k%W?uiev&P=CO!5_H1G&t8=PaGK z-sh^aH!b4|yS(HoJMRK6?TV|BcpHI5H&c0BrmE~Q@wijUi6apek~g8^$>nio*77={ zu}$SoAU#rEX|$!K)nqiG(#P2g?uzDAdE}Vq`sPd|oA7B)vu_`dWEj(9CUgQJWV z`YcTK6&W4kkqI#rm6BnZim;M4lm|5%HY`=B`T?dssA(p*nQz^N`5L~x&O@?O1~G?c zZ4p1l=;cDy?)C(Y|243So^EjOEzcd&{XPfY7d>OYk<;qj2 zc2PoBc!R{kj(VeD3wD!tysJ$XH#$TpWp>|Qa+Zm{_sEynp^aOuJO+ktdKJ!|gMD-3 ze$vVE8#_o3>uaokj2He{kfqpq=_P=>SXKibBjseIc+B)Xe00;WoX~}+azduM5J|`} zRX0iT2_8%ye@{-TqNdqwqkrYMKt{#xf`!C??NCm2P0gf4lbSXf?X9r3^bCJ_bEEU4 z&^ni%vg%n|^^Bz&PTAb%=Zo7=>f_5qFEsneVfM3T@BA@q+EQ!Zv5YIarP(Pj+n{FF zRx@L%fekQ5?NLGd&6YbxB52>+c8*k)?ukk<$*szCJQ9-K5!D@*hp7~n!#rpn2lcYa zmWHWz+zs@dR}Nm4jmImWGM=5n44aNbaPj*qrV3-%wxctEKgMKU~e$c(bdz@ zxhFt*+s#)K5>1HnyX)qjK*yeeo{#7je_&^@!w)L(+VNyj(!rWqy^!6*t!-qKU2MIX z(>d$z{FU2(qs-5qYzvsT{km}b%~dY;dYdn2yPLaj@=GnbyWU2gVJ{xoko#$5VF**&Zx56a zZ>IC;)~>$2dv^^C1pJqcR09^B(8XrbZ?lS_22!OxI@Cwj-vG%SV#KsqXzOyL8yKZy_EDl)xrULkO!7_>?x?HAIvY?7_zj1(A4z6J}uaEVN!65h<8z|l$O8{Jnog~QVbJc@kz zNxlrATO+D+RG~2`L7UmvM;(vyY!GNnDX0I8ocvs;9$YjVmeS^{@N^SZ39dzSioOM~ z_*zApz#PXaiK=Zm_AaTyc=W;xVj<(`($b>e6Kf!6*b}kt;%l%57fB`m+;!l`NCWIf ztb3{p#dv1;n{fk9@m-qAN7fNViPEDm*DYgIf#f76=m;(!L*TU)!x3+h3i6pEkb~n$ zJAsfY*Kj11pr6F~IRw0U=<^64egQEX;RgsmMEEhnPY`$+-^7uQa0lUS1n#YXv2`GP z18IJQPWIP$WnBjm>i$?%JtyD*UX3ej=FEI(F_cta3eT>pyJzL|Zf&bFL-KsW`mYY$ zGr;Fwn5{hCTfub|gF;UwEyW#f!B{s(mEqw?e3<^nz@9$tCC%*G@wM;}ym7p<4NnZk v(CSvWQuhEOygrIil;;R_EjAMwEiEx6oQ%qCbRBz)4%#NH#P_ZNk^AyLF>_qz diff --git a/src/auto_commit_service/scheduler/__pycache__/daemon.cpython-314.pyc b/src/auto_commit_service/scheduler/__pycache__/daemon.cpython-314.pyc index 19ef353c04ed810a865d769b8656e5c20dacf99a..bd55e523012868384482f1871c1e23b244f9ad3b 100644 GIT binary patch delta 12057 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 delta 6737 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 Py#1_~9{G$Q3Pb)6o>k)_ delta 1478 zcmZ9LT})g>6o6;$-o4BI-2%(cE)C0N3oO^N6xgz0`7yBFlGs4gLQxyZX3Jja;$_#) zT||@!CK?~C59GXWNy>=fS8hlzuYHiD?~hzz+K`D>Z{qG4&dyrxU6oo`_saIWD^+75dSpDPtbX{)h~ z>Ugc)xM<`JmMI$P`NHyYu9#jnEGx5Uu#>nofQZ8P!BaE_YG~5ijEYu72P}k!Xc#^T z#b{sYVd$btPePvI#8@bBspv+!!TJdD*6y{L^UFTXaY@d z-55vFkBA~>5F)O6lrR_DHGMgmOifR-7^=Dv#}Fw*KSD*EMGSD*PP4FTFujT$q%wuZ z3uyG18LOBU<+NQH_)M=0oacJ0iUXen2Mfbbx=!zujy<*GqSLU~8|68dd*?PPk>g>r zi02SqgvjGat|A3dkmu3mAp9qxR+1LsV-0lY(U4!njUqlLmo(+y==S@@s8p(pCnZHx zJqmOEA*oE^)&8);zFa3u5?t>Nz|SoKmEA8Ye6JWwZrJoRLfjvaKOk8N-cOvMe(2?% zUnMlELOD@SYv2uUSSr@Sj@Imumm1LAE-wZDJL6!^%J-bx7#APYq$oD})}?g^KU-Os zmzv;WPhD-+byL1qwe2|U*MxrmR}YXIH$HW&Qr!*8;2HREFjhY`!wZ5fz(kUj`oVXD zJsYfzYjsupG4b2%#(6Wdk~Pu`8PmL)nSUv5&XMz?n|lU zh1t}l)Y-~2J&U(uM;>~TO05Zjt*4vaVRXTlgkSrb`d4$sYiVZ87hW;g+G)xg>PK$+ zh5Wfm$|~_yKk_#3dz(LMyB+&D_9!y3ADQ^pR|{9p?A465ClhoxN|UGM-Oh1;G6C_S z2Xqns9) z-^kcx3mO%KNPLn@wj-A>vN_bH5u#hg#}Yj{#&vfI)6gXH#V%loFx(uub-u;v`9Teq zoqR4Uq$XT;p;Sex17$Z#9^yIv*o)FQ^*Oulc*}%OJC5IRsvL`l=^87*d!zUJOgvuv tB5~1mTxtls+^!m4E@W3sW0bwlm%PTrnuT|tnXLIkNjhoQZv-j){{bXEKiB{O diff --git a/src/auto_commit_service/scheduler/__pycache__/processor.cpython-314.pyc b/src/auto_commit_service/scheduler/__pycache__/processor.cpython-314.pyc index 95c054d24474d00dfd740c7ae63c6f9d60029218..dc93bddaddd452a569746f92d893688b14d2bdbf 100644 GIT binary patch literal 17825 zcmd6PeQX;?mS;7;zeG_a^+`%Q56gCBOO_Q`k|o)eEK{SY@iZf4$!Tb3GPfBV=KeX^ z){HaB{&DYBcas!N#hJkzum!5Ry1G7IRlTZu?^mz1+ge~E;M%*UgFkqTkblJ&#cAZg z{r>}j%fw4!*XCnmoyjA5=)rJZs34mHQd#Jyz99yw+1ptlDcTC0=tW z3E5(7F{vS53%nQXSIOyWyi6VO6vo+cj&I?)g-A3Qi}07&naKQnFvc$Mkr^%;jqt5w z9!4|-{4p*ToaZ2H?^}#T`e~{OE*1-h=b|3HX!53u5KVKzm@gXh#}=ca0mFgd?5t?U zkUtRc`9mQoiBy%8WMMISQM5)E=jZ)=FwW5|9*t-i3dRO`KEjLkQI4PE`Xk}lP;f?$ zD;kGfUhXMwCdLJ%WQADE!eS`o^KG zP3mZj7d00mkq}g_n~m`E{#X>NtQA|M{7jo4hRG*&u`epMvn@JvkqayWeQlZXUAQD# zd_I3T9D&AhJ|ABRWwgLwvUUwwpPvIZgslwVPCvDP|w^3$U+Y8q1{4MwEQViU`>y$Ij7y zJYgoJ3Z|+O+f3?+5o6TZF*T1USD8lHc|02bHE6;B7vuQ(V3=crv#dYN((zztAhZyP z0aFEmuP?C|IF{#TBF}O>7ho@3V*5k>#Q@i8GD!iN{vsDzV4n-dE_Rt(SjyHg>m&iJM`9<23K!uVeICn9Y)qyzo_OQqNp(w`! zd$YmtEbj-VUz~wrHQww}_nM{&nMnaw`nou2r*yqV*Z8bq| zq1*vnazGtqZZKmvV5*6#)^<_9;E%yjheb1Ol`j-|j^m?PbR&D2cf(UO9-iaE-17_k z5wXb^jKW$&ha4&P(M+v}Ly;Mv{77p$3?>3)(&}p zA4M+zZjqCjJO*@VX{DmtAHF1(`^HX<`MiVur=|wIeMe6Y`o{YvCkMS_6CM>`3c2_O zEE-pd#>XZ4it`f1?}j9FW)DE%i_2uQi8#ux?Y_GEZ(A;(_+_E}Z=&n=iBAuC*X$E7 zM_-Drn@9+!w2_)9zNCUp0&gXf2aK1pH>Y^SR8gE4gpiNK~B z(|B!D1ZKAyXSY{_TU3aNX=$96#_2FFrt=ojI6aLs$m#Sn&Pd~6i-U9q8iQM%0XI2_ zG18a<8e^p~CU0TPJVjy_FRrO}u~6C%kN5)kgG9eITp`CG= zJYfqfU&s?|IK2@((H_Q>)KNJ^6~8eO4&oXLn?H+dLS}<9Wvw%r&gx=Mo*ZSRj-w-` ztT;F`dAg|4l}YK+E>_;zStTa3aQWnZ?qW|Z;A-d($xD(PPs^9*_$AYrN6ohZ={#=d z{9f=tP|-xW&}>dLozjiqq)BP;`GU|!pHD1%co?KFbO@YKBFxPS;%a!QFjdCBRFJA{ z{%1pl)Z5sHN3lm&xef_CT`b-=+CPhfprbiiaSm5uw$Q!=^Ib2$rry)vmXTX%Sx`->#*ue&T)H2C zxwiEKZXG$!tIOZAKe``~!E&5e-zjqiv^D)L@Aw;bqQ+~S#`TUmXti4jXP!zgS%}xP zEiLX?IW8-$d0SdGCn3CMrL}YzmA7g#U8kh|14m6gl@?Ivpo~Y3P{B@pl07FfWd>l@ zL76BaP&cJkXdX3XV!c)+c0uz^dtgcvPID^EK{DQ?)RB3Pqr{QprZo9m0ON>KTaNP< zDl_9De%C&Ndu;jZ0gfJM&D>*O?q{z?~+?d5fXeyep*F2&Ll&mE&^SonF!Mm-C1ftz^eKRNGdxG!1!Y zc`1}~IGrRNfN?6zPt_mYh9l|1(}DbTPinp8opQg{5j`1HoqQ8~=H$<*-^-HeR;36X z3Bac4CJVYOe#|#kMLV?y#!B}`w<+IFW2fb1jlrU-5_XFPU9YZAeg>Io+~lc)7R-I4 z7C63n3nt0<0j2!Rb27beFFb1YI=`l_oY||i4aVo!QY(W@kaVjnNsyuA^(poLJB-@n z3N6s)C%;jfE53$~oKb@|_bcURo|DWYW|2!8t^H~#4_zmK_oRJYPfR55=nW_}KuhRK z@ksu2|Nm~u^pHZ+q)u5e|G-wE08AaUipp)-0_z(Ioax(zl0B|t_YQ!Aqm7vVYx+OwLvynx3Zwg0P#6CR$5oO>M6wbQ< z?NL-tgi&OLC?JSc!W+7>&WllB|yyPn*!i-cXB1q}Uhs&vT+qs*xfSV{z+PB;EdCm<0u+ z2L_MFl{jA1FL#X874Z2>71Uxxn&-H{9yV@f=OX|f2kDE6T@1%~|IE`|Al?eaBC5<@ zSOnC|4?4SCR8uJUGzU0bn0t<$4TiX=2XG@+L~O@`8GI7Ne2J1F>Mrp9@XW<{$&jQp z0%oVEkvMR1H|m%&cnYC7Pr}0Ccl)4YuiqCexLod4>Y=pvWSOF2Bf4`BH+;)2Jb4{?fJ`cZ3QG z0BV;>h6Hi<83ec}vM$HU42Y~2x95KCVm*zbE)w0$wMh>1KfqhIngwB%GW>KH#RglA*w@Mm@*i! zhiFiELo}utgGWV>M@>#N)8WSx2QEMrbFoy01~>&4mph0*ikSdWCK8;6TdG*(QwGbY zB-3LG1Af%YbBV`QSTv?*8;?4!SS;fSKE!wxZ155fkR##CX@7>PFz2I4RAVCou`DZr4GKfxycAs$@5pl= z&UDhb7a}0Lkmxh8-ykZvWhchMm(4Glg_4%#zz>5rg3IRw=b?2&*QO@O7_FZwcws!&Y+5deth_9A2IL@!7Y}uAUI8hu3W*8>LODs@m6ruLd_(HBrR(1;&N4E5uGW#ac6xp||#ND_Qcq90FaLv`8EN;JY>@!Ds($N4v!O?&{fIUObVq*DVdaG4lGzQup$O4M)i<&t7}s z>I-X7u)T39C`J6m)xTJC>=Nuv%VrvpEZvnT-L>Xu66~JkicP(`=)jg*TVUO?k&4=- z`ZqkUd)CVLBprLM4E%3L>E{x8LiOnFz|Vpo1aF@cD$lOlzV$#y+V*`fyfnF9()>TH zH~F=L$FB@+)HW>5CL141G(NUg+j(VZ-BP`&aTIu&6kGpB;p>G-b|}FPrD~MEOSx)Z z>v^?jQ%`D!nfpXjV}C$2F8eEbXkbz4HS<-oP_=($@~yLPo?SVy%HP~|vs`eWShtbdI0->&EAx>GzpfbEgh+AS)Tmi*&An9^=q|{C*6-<8U4(`CLK-i6C6!)PYcz1 zSL)yLyy;nStsY%{A=&Fq^m>IO6GG+Wy6sF(ze@wVdwDdur#G>uSJ?fyP|=q)wibCH zt~W0|nQSviDvsakktmfv)%hxW~DBi|7jMY4W>Q2Yx*A_Q-1Y z%?r1SZmWgLlk2w8ymTK}@vlq>6^AInzeQ&J3VPPruthX5C=YSos%mxbYMoGdWZl;L zSw&T{qCHX3zEZMQaqtyACZ^+YXtn;wp0_=#uA4`1K6f)HxW|*W)1TN*f3<1ELchFc zB?X>)I#Suke6iI;Y_&kV(Yj%=zkKq=lY%Qf-Q>#3kE~mIQ{|P(@_mW&eJPuB!&aHJ z)g^3oDSPeG-laOh)_7m9sjvcPU>|`84JojGwPhi;vh1?2_bfYqSbn2?*}T$0+g*NW z-O`n}=nb3WmA=2#?O1NPQf|`XPFUPRb-K%iN?_{Y4M%6Ej0b#q6>gyey8qC3-e$48bK3&$HGAPoq{q9H!!0mns*wDF?_gB2ak7E`1xIR zUk|+8BFt#H<`!edaDfN?&UWzMZ#pnqO>S2*qi)UZDi4G|&|`TYR5RoIH6O5*817-l zJ2f91!LmPe_SL}SqXSs>N00SY!^_9T`0{ZHgW+=OyBR3y<7)HxUiHV#eFbAZ>N}kb zyxcjcfkbx>V}?6D7Kr(o3FCie?sJXrQ45VoxUfeHQNmtKDnK^yyUb^r)d_8%#p_mo zQp9+jx=-vH43{wQ;geD=l=q3-f?*GhY3{R6>eXw9nTcNAT8{?8>kNKaS7Fk1Jtkdu z(wO2t)0qbKr`7oKDT|*!ZO~%4Sq0!m!fXqLG^ikXgzrd4-KV!6} zyVU=cwQN&MUv;FYc2iG-22xVKX{13DF}d!VG5GMwL>hg547PCzeFnq{>d1AO1L=Io z%E9N9gZn8sNb)j(m!Vid-Faq8eV)k%u@vmb2H3%|03i!nK+3e|nSW@}7C-jCBUpRgL2jP>##uD0szRJemafUP3je@U}k5=6_37hoYw?cLf-l4HBZu6 zJBhQ_GN}jZ3`(ihbV*hj__kXvI-0w(s?fFK>zGLlwqS49MZ-4km zDR>s0H-AS_tqk^< zpC<=6J3~uE`ZK86#F_s7!HEeLpdSiK$l#f2EN41^|A6i)`g zq~v?i8^SzgQi&81#IcA*=FvE1HX65ORVbBZr7;o=g_w?>_0Ix%2(c+WB-0=lDt|Vo zKLe~&MZpM))$rc}3PdenW`ObxBS|CZ9Y+t(zWGt~+QE|yJf-fC!V=QPrkrKv6>G^zv9xgoPi(cs#43_z8a!LpXu?bLfqs*96`+2xS&y=fDFK8!#J_ z?6O3?+;Gvn0KEr-Dvmzyhh#E{BEcxKnU|afAe8c42qpcA3acL2d=Nm{WC>_=JumkB zU^MC8mvHY}H}6Y1%0b~SF27>>ywrXD^pbhm|M!K-()KGuo2ssYlFu9!*H3@1d&60A z?Znj+OHIq2%bu0JE9X{5g}y1_iF3&(zMXjD+rpGzU@xpYXErK4sWSI###fE0>blon zc=d&3b!VcwbK483TCNgM42w%ZF)S_tm9U{DM`tyK&O&LIRrK>58sC&4&N=TXTKiiK{{KuS_z7F z@%XyobgH;KS=^Q=ZcABg8i>-QD{jc1pWS5G*KlO?UHG2wi?OPdmYvj$5mG0H2ZkOIR3a7oo#CgH% z6MPqhnSgMC6RKy|ZF4C{#k!;E7f$!@)WqreYRf>Jjax)tU{6Cu+4#yct2097(REvY zs{yq(cI~n-! zei!w7%wrDiZNuRayY>T(6~2C8w?GW&{OGfNmg9%CAMRm}w;4Wc(O`Hle)zCM4@o~f zgh@ZrVa!MRzKSuc_Md97jDKqDv%||Bh8fcs?x-{vrm61eG2b1l7INHiATir?Y8|u< z76ZiuHNUxcwmBfxrqLi!LoKr;{Fg3XXgtHCg}|dVW)DCq8QZ;fw8{dH>dW{dsmmBL zpo(mSkfb3arHVs6_Pc1G^%BHN8nTN_E4F56WtEl*l`Nn|kbGKlK6|VkQl=%@OqpIL zOP^Hb=#yzJ`QHOQ3!s_jlOz>=GH{+sqZzxfqD(855VZ@-qmyUrn4m`&E9s%#c~VcO z_44sNHdmn4<83`~)f~3M9vNpef-T-=3@XH8!R9vKjA1(u6LY+A=qbp_<^H5<9j}yW2Ryht! zAIZsLn{;JJY{-@Bl#{z{$>`$x5-fyN!m~6Rt)JU#0Fu9EylPC9y6|WzS=yE;ZQJ$& z@{|M7`2s}e;TXwEYCPX0Qw?TvS+AS`A>wbZg$R6=S%u&kYYaK7h3Es`p}eKQqvydG`S3dl%#lh(E+& zxSRSt)bBM9G3xhBy9N)d-`mR!?$^E7p~3KD490hAA=i6{EfBtC#F$&AUB?cqZ|!A{ z?bqGv&|sLRyhT&qI;@2>?=x!1wM|^W?T?BJ9T50~Ab52y1TX1nbc)~>0P+N^azs+x z08jd+7T)Jjlt8?Tg73Q#dk2q-68Hk5MAfDqLk41VY#K2n;qDN67OEOoDFq&75h(|J$7L$VO=13QQ}49!GoDW{(C$cwt|M*6OTp8edhm4|m(v{g zghM%y03$PfwqUiOnbPDt1W@`d09HHDZ-q*M`6RMQYh2fh=HzgttH0 zCi%9XVnX6+jaN=Q9b8zz4OIS?E`Zwmw0Gsb--h=E(b5X8728@rqZJ)8OoFQD7AmC4NKRDV_ZuZM7>W<=yvuL1&!OwyVP%)M5{oTq zu7qF0TnW}6Ew8sEYlq;Ms2%#;(X?EgbhLfqXp=#LR7n~n*d$EvAd?zAetZ9W=WdQ} zs+r;mW=oCMDR6JfBU{ISg-5EQ8bk!e7)CLe5Gpd(GCik+vhj7x=~R7Fvi`9|{bR}c zo&~OR|=XEFc=eWKFt~EuAzo6druEwtNM*I2V*aw>XP-&s_rEvUw99 zZ>#Cs!}phPI|5oQ_x~CKm+^lAFe7A`S%4EUSProzIWE0;LM}IG7NAdk?M)@=Lbw;O z07#eK8Zw3El!w}i7H|Vyyjw9}Wc^?;D4Q6{7`kjU#y$tPed(3CU^Ls3vDL%ye+5-6 z;s*4;ez45;1p*o4NgBKP+V}n*Y*FXoQnO@Isl>j)N+7x%i&_|@O~>NNfb>rVJX+BT z_wrjaF|Gt5x)kkGEQS+UfkiVXapiKbJlIX8hG_E zzd=s*6o_z<4^124BA?0U10zJZP!D0aME}g9KO}!C^!a9kd^8591Y9@*pY=XpATk5j z>mS3SXV8nG_dI%3!=a5UhHIN}4?j5L1E87@f_W5YHs z)-T_JMWHu{A8^6_;y*zb{9LpDfd+1C-oxvh4{GtYo^)65K}e0Z68ETW#e}L5ug8<7G3E#ZVx;3ywa5RPV%d4?Kp5+vJ0ww0&^g znHhF!O-!wQ<96j*I;gRbZ!rp1y(MAk$~s&y2Oi})KbV5THWDwPwb9J-1_(Ffqp^4~ z?1{OT*rAxBh0Im;02c=9;kXTqccCPD9i3W1$BSqEF@LBFPO_jOa?$=kyd3PY!MO7x z8{qIiL*P*mSdc=kQBN)ZGIXh^M=DT56;nBxS|@EToSr*8S2vuw883)2eVCov0rx$$b4dGVlqAPF1f^e#eI$%656qUq# z+)_n@vKR7Bd^OH-v6Ivum;W2gHH=;}db`o1%uPBz&(^8av@{fR9h+ukq#I}?ZJ+}-N9iN=*dLQ7A*P8rw4+E&Y~Ocp+>){h zHtop%o!|M+cfWJ)x##=7b51=&^C?S<#cUu@-ZoC8zt#A>rHWp8zUgd@o%o1ks3elH zOM~5n0jahSqP9%sE4n@h==#|O=<4PcoRYlyS)*=_4p-e=A0 zuI4Mc8rjEQH|+UZ6?7MPIkk`}h;k}-LY@z3WV9n!006H=?gH4Hx$H)P2f+)_0skzL zkC(|!GNKVI8w#FUEGqSC&!{SZ@g6o-Yd$ocdDb{4@=h|jlex>>2ggZl7d(DPi4ET& zfaZVDjDB8Ist$8(*-|O!#&xkic4$|P;|MHOEtwoGDN8lb6=DmWmF)LMt>!3Y->L9W zCp%qHE!0BSURLzm1sAX&DB0N`>P&3ES?M<9sv$x|GP@t=xgfGnjUMX3 z>9lyqMHA`ZyQr$=!G*ZD^u+CYqH|y+b3_ zu^-sF=^mDc&iXB#oixE_?UBx8$tKJOIL>CWBqFhiTl5x@8o*8!E86$dMmFGR=lqNF zY{AjUUUckb#>!b=K}gARMn14;Igs(r9G#v&lFEA1^Iq6qEnr0svTs*9=py@ZztMcwzw8ltKk~>-3MQJFFX&Sx8qmx2I8GBn5KZv2>BEN$+ARBJjW1p>ZVr+? zF_+8YF=lCb>4N=8CrFQ*1fG)y}hg6-u3$C8+xJ2S|mcb^}`3)Z(MIBKCIo_`qt=gpyuG-WPGko!pvTOf2za z%_%_7niqA~{Ah3uMh%j+pfN$YwQ%3~0C%aKj(3TdI(Xzg6y%q}sDG&+ZC@G?KysOK zAi2yNC%U-H+ajiml}V$hRbM z5+A1zP)PvPwDFKmMH!Qm>I(^A1(TXCr4(*|IgXuo0R%WTVI4rhm&;ne0M%?KfReR3 z15bq+j#QdcEvEF+)*S=7?%*r zD3Q2hz#pN@+?Zg1DNJrtd%nz&cmF?zTo95%tPGN^Gcc~?T5D+nF?)&Kt|cB;!m*iu z^_EFI$tXn;-`8JZ#M6#aVzsbfHYQqZ)+8qhx6>}n8V(hG6-GLFOPQT+u!)igQ)vL> zzV0onf|+{kJ@}u3zYcPwzcdDE>NV%Q;t*eQ4vC8h` zlD%L#lFn_%tdLFTGV-IUiUsus5b$N?eF%3WD0y!$vM>TH4Uu~h(7j~*uri!eh^!>Z zdyowxv?Aa>l`&few54R$4ifZW)n}F2;UPnYeL}M6Ja}k@Jf@y4$3Va;dYWvCmp%gl z<9%?bzgvjDqsX&;JwGzsPDSh=J=d1Bql7*k;iCQIteHl;`LmXY78>X5G#cj5Iqb-T z5i3-$4^hy4eP=uH^C24T<WZSevO_?fL2i_=r*_1aZpSyw z_3H8|5sg1@XUDP7ek+O=SK7dpWYrsAq)-XUl zfnm+cmV28tv)9r(y({>>ZzG+^m!___}l`YY_YCKU_1q$bJ1up;|rzrzMZ z+rdk^QZy`SiKr#%So=T))w7X-KK93fjxzPg34^HHw}*KKLl(Ii1Obb3y@C_p!9ka_ zb?X;I^_(XwZgI;G3VLZ|_r1vxX(Xzei=$z5gn&@m{vc4lFIye-h|2xx9`?~-bF1>b z-UD6S;6)2Dm0dNu;FmYLUTXMh>#5eOb))dh*Nwhwva*+lF4k_3YU!&H3V61IMg{(C zryck?ePl4IWl!!L-mPpY9Ic=qP3Pipl{}GEvm}*qCw=jaZW}Z0YJht~`>yxtQRa+1 zG$`ZoUp|TuMa$aR)LaS<-STcU$f>WXydmmjF+zentIj;iE=2rv8~baduLkobsN)Ux z_RTdw4+KnX-|$X*1Iq757(-CP$|!qzIOI{TpLlTCr5bf$KLW00b|>2yuI$CDr+VeQ zd4R_pjtTwdF$z1oh+c4Wn3{y(M+89G>B{o~ue`vb(bwAM(4z9e(d;WkRYCIw-N5n8 f?1{P5ko*`laTeKe79QDOep7smqrvM0QPKYw#oA|E diff --git a/src/auto_commit_service/scheduler/daemon.py b/src/auto_commit_service/scheduler/daemon.py index 1c4b7d0..c07081f 100644 --- a/src/auto_commit_service/scheduler/daemon.py +++ b/src/auto_commit_service/scheduler/daemon.py @@ -48,6 +48,9 @@ class CommitDaemon: lock_file=settings.llama_service_lock_file, startup_timeout=settings.llama_service_startup_timeout, health_check_timeout=5.0, + fast_model_id=settings.llama_fast_model_id, + reasoning_model_id=settings.llama_reasoning_model_id, + use_model_boss=settings.use_model_boss, ) else: logger.warning("Service manager disabled (autostart=False)") @@ -388,7 +391,7 @@ class CommitDaemon: if health == ServiceHealth.UNREACHABLE: logger.info("Llama service unreachable, attempting to start...") - started = await self.service_manager.start_service() + started = await self.service_manager.ensure_service_available() if started: self._service_crashed = False self._service_health = ServiceHealth.HEALTHY @@ -398,8 +401,9 @@ class CommitDaemon: return False if health == ServiceHealth.DEGRADED: - logger.warning("Llama service is degraded") - return False + logger.warning("Llama service is degraded but functional") + # Degraded (e.g., CPU-only mode) is acceptable - commits can proceed + return True # Service is healthy self._service_crashed = False diff --git a/src/auto_commit_service/scheduler/processor.py b/src/auto_commit_service/scheduler/processor.py index 92ebca1..c8e51f3 100644 --- a/src/auto_commit_service/scheduler/processor.py +++ b/src/auto_commit_service/scheduler/processor.py @@ -26,6 +26,45 @@ from ..recovery import ErrorHandler logger = logging.getLogger(__name__) +# Infrastructure error patterns that Claude cannot fix +_NON_RECOVERABLE_PATTERNS = [ + "couldn't find remote ref", + "remote not found", + "repository not found", + "connection refused", + "network is unreachable", + "could not resolve host", + "authentication failed", + "permission denied", + "unable to access", + "fatal: could not read", + "no such device or address", +] + + +def _is_recoverable_error(error: str) -> bool: + """Determine if an error can potentially be recovered by Claude. + + Claude can help with: + - Merge conflicts + - Pre-commit hook failures + - Rebase conflicts + + Claude cannot help with: + - Network/connectivity issues + - Authentication failures + - Missing remotes/refs + - Permission issues + + Args: + error: The error message to analyze + + Returns: + True if the error might be recoverable, False for infrastructure errors + """ + error_lower = error.lower() + return not any(pattern in error_lower for pattern in _NON_RECOVERABLE_PATTERNS) + class CommitProcessor: """Processes commits for a single repository.""" @@ -313,6 +352,18 @@ class CommitProcessor: ) -> RepoProcessResult: """Attempt recovery using error handler (Claude fallback).""" if self.error_handler and self.settings.claude_fallback_enabled: + # Check if this is an infrastructure error Claude can't fix + if not _is_recoverable_error(error): + logger.warning( + f"Skipping Claude recovery for {repo.name}: " + f"infrastructure error cannot be auto-resolved: {error[:100]}" + ) + return RepoProcessResult( + repo_name=repo.name, + status=status, + error=error, + ) + logger.info(f"Attempting recovery for {repo.name} via error handler") recovery_result = await self.error_handler.handle(repo, error) diff --git a/src/auto_commit_service/service/__pycache__/manager.cpython-312.pyc b/src/auto_commit_service/service/__pycache__/manager.cpython-312.pyc index 1d00dc0978865254cb35df544f3b58af1ef3994e..d2734d1a187886ea4c211fa3fd3e0a05e2f4e8c6 100644 GIT binary patch delta 5484 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 diff --git a/src/auto_commit_service/service/__pycache__/manager.cpython-314.pyc b/src/auto_commit_service/service/__pycache__/manager.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..032cd3d3526a373de1d2761f749baa916784b6be GIT binary patch literal 20917 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 bool: """Ensure service is available, starting if necessary.""" @@ -66,7 +74,42 @@ class LlamaServiceManager: return False logger.info("Llama service unreachable, attempting to start...") - return await self.start_service() + + try: + # Resolve model paths via model-boss before starting + if self._use_model_boss and self._fast_model_id: + await self._resolve_model_paths() + + return await self.start_service() + except ServiceStartError as e: + logger.error(f"Failed to start llama-service: {e}") + return False + + async def _resolve_model_paths(self) -> None: + """Resolve model IDs to paths via model-boss. + + Raises: + ServiceStartError: If model resolution fails + """ + try: + from lilith_model_boss import ensure_model + + if self._fast_model_id and not self._resolved_fast_model_path: + logger.info(f"Resolving fast model via model-boss: {self._fast_model_id}") + self._resolved_fast_model_path = ensure_model(self._fast_model_id) + logger.info(f"Resolved fast model path: {self._resolved_fast_model_path}") + + if self._reasoning_model_id and not self._resolved_reasoning_model_path: + logger.info(f"Resolving reasoning model via model-boss: {self._reasoning_model_id}") + self._resolved_reasoning_model_path = ensure_model(self._reasoning_model_id) + logger.info(f"Resolved reasoning model path: {self._resolved_reasoning_model_path}") + + except ImportError: + raise ServiceStartError( + "model-boss not installed. Install with: pip install auto-commit-service[model-boss]" + ) + except Exception as e: + raise ServiceStartError(f"Failed to resolve model paths: {e}") async def start_service(self) -> bool: """Start llama service subprocess.""" @@ -196,19 +239,50 @@ class LlamaServiceManager: return False async def _spawn_service(self) -> asyncio.subprocess.Process: - """Spawn service as background subprocess.""" - cmd = [sys.executable, "-m", "tqftw_llama_service"] + """Spawn service as background subprocess. + + Raises: + ServiceStartError: If no model paths are configured + """ + cmd = [sys.executable, "-m", "lilith_llama_service"] env = os.environ.copy() - # Enable mock mode if no real models configured - if "LLAMA_SERVICE_FAST_MODEL_PATH" not in env and "LLAMA_SERVICE_REASONING_MODEL_PATH" not in env: - env["LLAMA_SERVICE_MOCK_MODE"] = "true" + # Use resolved model paths from model-boss if available + has_model_paths = False + + if self._resolved_fast_model_path: + env["LLAMA_SERVICE_FAST_MODEL_PATH"] = self._resolved_fast_model_path + has_model_paths = True + logger.info(f"Using fast model: {self._resolved_fast_model_path}") + + if self._resolved_reasoning_model_path: + env["LLAMA_SERVICE_REASONING_MODEL_PATH"] = self._resolved_reasoning_model_path + has_model_paths = True + logger.info(f"Using reasoning model: {self._resolved_reasoning_model_path}") + + # Fall back to environment variables if set + if not has_model_paths: + if "LLAMA_SERVICE_FAST_MODEL_PATH" in env or "LLAMA_SERVICE_REASONING_MODEL_PATH" in env: + has_model_paths = True + logger.info("Using model paths from environment variables") + + # Fail if no models are configured - do not fall back to mock mode + if not has_model_paths: + raise ServiceStartError( + "No model paths configured. Either:\n" + " 1. Install model-boss: pip install auto-commit-service[model-boss]\n" + " 2. Set LLAMA_SERVICE_FAST_MODEL_PATH environment variable\n" + " 3. Disable llama_service_autostart in config" + ) log_file = self._pid_file.parent / "llama-service.log" log_file.parent.mkdir(parents=True, exist_ok=True) with open(log_file, "a") as log: log.write(f"\n=== Service started at {time.ctime()} ===\n") + log.write(f"Fast model: {env.get('LLAMA_SERVICE_FAST_MODEL_PATH', 'not set')}\n") + log.write(f"Reasoning model: {env.get('LLAMA_SERVICE_REASONING_MODEL_PATH', 'not set')}\n") + process = await asyncio.create_subprocess_exec( *cmd, env=env,