Преглед изворни кода

fix(cli): show background server startup status

Dax Raad пре 1 месец
родитељ
комит
1c67004999

+ 6 - 0
packages/cli/src/commands/handlers/default.ts

@@ -18,6 +18,12 @@ export default Runtime.handler(Commands, (input) =>
     const server = yield* Server.resolve({
       server: Option.getOrUndefined(input.server),
       standalone: input.standalone,
+      onStart: (reason) =>
+        process.stderr.write(
+          reason === "version-mismatch"
+            ? "Restarting background server (version mismatch)...\n"
+            : "Starting background server...\n",
+        ),
     })
     const config = TuiConfig.resolve({}, { terminalSuspend: false })
     let disposeSlots: (() => void) | undefined

+ 3 - 2
packages/cli/src/services/server.ts

@@ -11,6 +11,7 @@ export type Args = {
   readonly server?: string
   readonly standalone?: boolean
   readonly mismatch?: "replace" | "ignore" | "error"
+  readonly onStart?: Service.StartOptions["onStart"]
 }
 
 export type Resolved = {
@@ -46,7 +47,7 @@ export const resolve = Effect.fn("cli.server.resolve")(function* (args: Args) {
   }
 
   const options = yield* ServiceConfig.options()
-  const endpoint = yield* resolveManaged(options, args.mismatch ?? "replace")
+  const endpoint = yield* resolveManaged({ ...options, onStart: args.onStart }, args.mismatch ?? "replace")
   const reconnectOptions = { ...options, version: undefined }
   return {
     endpoint,
@@ -70,7 +71,7 @@ export const resolve = Effect.fn("cli.server.resolve")(function* (args: Args) {
 })
 
 const resolveManaged = Effect.fnUntraced(function* (
-  options: Service.Options,
+  options: Service.StartOptions,
   mismatch: NonNullable<Args["mismatch"]>,
 ) {
   if (mismatch === "replace") return yield* Service.start(options)

+ 8 - 1
packages/client/src/effect/service.ts

@@ -32,6 +32,12 @@ export type Options = {
   readonly command?: ReadonlyArray<string>
 }
 
+export type StartReason = "missing" | "version-mismatch"
+
+export type StartOptions = Options & {
+  readonly onStart?: (reason: StartReason) => void
+}
+
 // Read-only lookup: registration file plus health check and version gate.
 // Never spawns; escalation to start() is the caller's policy.
 export const discover = Effect.fn("service.discover")(function* (options: Options = {}) {
@@ -47,10 +53,11 @@ const discoverLocal = Effect.fnUntraced(function* (options: Options) {
 
 // Idempotent ensure-running: reuses a healthy compatible server, replaces a
 // version-mismatched one, and otherwise spawns the service command detached.
-export const start = Effect.fn("service.start")(function* (options: Options = {}) {
+export const start = Effect.fn("service.start")(function* (options: StartOptions = {}) {
   const compatible = yield* discover(options)
   if (compatible !== undefined) return compatible
   const mismatched = yield* find(options)
+  yield* Effect.sync(() => options.onStart?.(mismatched === undefined ? "missing" : "version-mismatch"))
   if (mismatched !== undefined) yield* kill(mismatched.info, options).pipe(Effect.ignore)
 
   const [command, ...args] = options.command ?? ["opencode", "serve", "--service"]