diff --git a/src/local-model/install-job.ts b/src/local-model/install-job.ts index 44098e9b..b518836a 100644 --- a/src/local-model/install-job.ts +++ b/src/local-model/install-job.ts @@ -84,6 +84,7 @@ import type { LocalModelConflict, LocalModelDeveloperTools, LocalModelErrorCode, + LocalModelInstallError, LocalModelInstallRequest, LocalModelInstallState, LocalModelInstallStep, @@ -458,6 +459,16 @@ export interface LocalModelServiceDeps { export interface LocalModelService { /** The `install` object of the GET. Never throws. */ view(): Promise; + /** + * Whether a session may be started on the saved endpoint `endpointId` right now. `undefined`: + * yes, which is also the answer for every endpoint that is not this feature's. Otherwise the + * error that refuses the launch, in this order: `runtime-not-running` (the runtime child + * Codeman started is not alive, so whatever answers on the port is not ours), + * `port-in-use`, `runtime-stopped`, `model-changed` (the digest is read again and is not the + * stored one). The session launch path asks this before it starts a session with the + * managed endpoint, and `boot()` asks it once. Never throws. + */ + launchRefusal(endpointId: string): Promise; /** What the GET passes to `recommend()`: the stored measured total and the runtime download that is still needed. */ recommendOptions(): Promise; /** `POST /api/local-model/install`. Answers once the job is STARTED; the job runs on in the server. */ diff --git a/src/types/local-model-install.ts b/src/types/local-model-install.ts index 5d625d7a..d964e53a 100644 --- a/src/types/local-model-install.ts +++ b/src/types/local-model-install.ts @@ -116,6 +116,8 @@ export const LOCAL_MODEL_INSTALL_STEPS: readonly LocalModelInstallStep[] = [ * | `runtime-unpack-failed` | `/usr/bin/tar` failed | * | `runtime-start-failed` | the runtime was started and never answered `/api/version` | * | `runtime-stopped` | installed: the runtime crashed and was restarted 3 times, then given up | + * | `runtime-not-running` | installed: the runtime is not running (the person stopped it). Only a | + * | | refused session start says it; the view shows no error for a stopped runtime | * | `port-in-use` | another program listens on the stored port, or no port of the span is free | * | `disk-full` | a write failed for lack of space | * | `pull-failed` | the pull still ends on an error line or a cut stream after its retries | @@ -137,6 +139,7 @@ export type LocalModelErrorCode = | 'runtime-unpack-failed' | 'runtime-start-failed' | 'runtime-stopped' + | 'runtime-not-running' | 'port-in-use' | 'disk-full' | 'pull-failed' @@ -218,6 +221,7 @@ export const LOCAL_MODEL_INSTALL_LABELS = { errRuntimeUnpackFailed: 'The runtime could not be unpacked on this Mac.', errRuntimeStartFailed: 'The runtime did not start on this Mac.', errRuntimeStopped: 'The runtime keeps stopping, so Codeman no longer restarts it.', + errRuntimeNotRunning: 'The model on this Mac is not running. Start it first.', errPortInUse: 'Port {port} is in use by another program.', errDiskFull: 'The disk is full. Free up space, then try again.', errPullFailed: 'The download keeps stopping. The network may be damaging data. Try again or use another network.', @@ -259,6 +263,7 @@ export const LOCAL_MODEL_ERROR_LABELS: Record { describe('the fake runtime: the child process', () => { it('holds the real log lines with the device total', () => { expect(REAL_INFERENCE_COMPUTE_LINE_MAC_MINI).toContain('total="11.8 GiB" available="11.8 GiB"'); - expect(REAL_INFERENCE_COMPUTE_LINE_MACBOOK).toContain('total="37.4 GiB" available="37.4 GiB"'); + expect(INFERENCE_COMPUTE_LINE_MACBOOK).toContain('total="37.4 GiB" available="37.4 GiB"'); expect(MACBOOK_MEASURED_TOTAL_BYTES).toBe(Math.floor(37.4 * 1024 ** 3)); expect(fakeRuntimeLog('37.4 GiB')[2]).toContain('msg="inference compute"'); });