zettcode-server 0.4.2__tar.gz → 0.4.4__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: zettcode-server
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: The HTTP face of ZettCode: a FastAPI server that drives the SDK
5
5
  Project-URL: Repository, https://github.com/Chang-LeHung/zettcode
6
6
  Author: Chang-LeHung
@@ -36,7 +36,7 @@ from zettcode.sdk.models import remove_model as remove_model_entry
36
36
  from zettcode.sdk.models import update_model as update_model_entry
37
37
  from zettcode.version import __version__
38
38
 
39
- from .runner import NoModelError, Runner, prepare, result_payload
39
+ from .runner import NO_MODEL_MESSAGE, NoModelError, Runner, prepare, result_payload
40
40
  from .runner import Request as RunRequest
41
41
  from .schemas import (
42
42
  AnswerOut,
@@ -151,7 +151,7 @@ def stream_of(runner: Runner, request: RunRequest, *, resume: bool = False) -> S
151
151
  if runner.busy:
152
152
  raise SessionBusyError("A run is already in progress; wait for it or cancel it")
153
153
  if not runner.ready:
154
- raise NoModelError("No model is configured; add one with POST /models")
154
+ raise NoModelError(NO_MODEL_MESSAGE)
155
155
  prepare(request)
156
156
 
157
157
  async def frames() -> AsyncIterator[bytes]:
@@ -176,7 +176,7 @@ def message_stream_of(runner: Runner, message_id: str) -> StreamingResponse:
176
176
  status line is still possible; what fails once the stream is open becomes an ``error`` frame.
177
177
  """
178
178
  if not runner.ready:
179
- raise NoModelError("No model is configured; add one with POST /models")
179
+ raise NoModelError(NO_MODEL_MESSAGE)
180
180
  try:
181
181
  frames = runner.stream_message(message_id)
182
182
  except KeyError:
@@ -326,6 +326,8 @@ def create_app(settings: Settings, *, client_factory: ClientFactory | None = Non
326
326
  @protected.get("/settings", response_model=SettingsOut, tags=["models"])
327
327
  async def settings_out(runner: RunnerDep) -> SettingsOut:
328
328
  """Return the model, effort, permission and harness a run starts with."""
329
+ if not runner.ready:
330
+ raise NoModelError(NO_MODEL_MESSAGE)
329
331
  client = runner.client
330
332
  return SettingsOut(
331
333
  model=model_out(client.model),
@@ -572,7 +574,7 @@ def create_app(settings: Settings, *, client_factory: ClientFactory | None = Non
572
574
  if runner.busy:
573
575
  raise SessionBusyError("A run is already in progress; ask again when it ends")
574
576
  if not runner.ready:
575
- raise NoModelError("No model is configured; add one with POST /models")
577
+ raise NoModelError(NO_MODEL_MESSAGE)
576
578
 
577
579
  async def frames() -> AsyncIterator[bytes]:
578
580
  try:
@@ -186,11 +186,18 @@ class Pending:
186
186
  )
187
187
 
188
188
 
189
+ #: What a request that needs an agent is refused with. The server opens its client from the configuration file, so
190
+ #: the first entry is what makes it ready; models a plugin offers appear afterwards.
191
+ NO_MODEL_MESSAGE = "No model is configured; add one with POST /models"
192
+
193
+
189
194
  class NoModelError(RuntimeError):
190
- """No model is configured yet, so there is nothing to run a prompt with.
195
+ """No model is configured, so there is nothing to run a prompt with.
191
196
 
192
197
  A fresh machine has no ``[[models]]`` entry; the server still starts, lists and edits the configuration, and
193
- answers this on what needs an agent. ``POST /models`` is what turns it into a working server.
198
+ answers this on what needs an agent. ``POST /models`` adds the file entry that makes the client, which is what
199
+ loads the plugins: the models they offer appear in ``GET /models`` after that and are chosen with
200
+ ``PATCH /settings``.
194
201
  """
195
202
 
196
203
 
@@ -262,7 +269,7 @@ class Runner:
262
269
  NoModelError: No model is configured yet, so there is no agent to drive.
263
270
  """
264
271
  if self._slot is None:
265
- raise NoModelError("No model is configured; add one with POST /models")
272
+ raise NoModelError(NO_MODEL_MESSAGE)
266
273
  return self._slot
267
274
 
268
275
  @property
@@ -641,7 +648,7 @@ class Runner:
641
648
  model=like.model.name, effort=like.effort, permission=like.permission, harness=like.harness
642
649
  )
643
650
  if client is None:
644
- raise NoModelError("No model is configured; add one with POST /models")
651
+ raise NoModelError(NO_MODEL_MESSAGE)
645
652
  slot = Slot(client)
646
653
  await self._join(slot)
647
654
  return slot
@@ -201,6 +201,8 @@ class ModelOut(BaseModel):
201
201
  temperature: float | None = None
202
202
  can_search: bool = True
203
203
  search_name: str = ""
204
+ provider: str | None = None
205
+ token_env: str | None = None
204
206
 
205
207
 
206
208
  class ModelsOut(BaseModel):
@@ -151,6 +151,8 @@ def model_out(model: ModelInfo) -> ModelOut:
151
151
  temperature=model.temperature,
152
152
  can_search=model.can_search,
153
153
  search_name=model.search_name,
154
+ provider=model.provider,
155
+ token_env=model.token_env,
154
156
  )
155
157
 
156
158