From 350b9b8e247bb1c24f49a884fdade18e44b115eb Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Thu, 25 Jun 2026 15:34:59 +0900 Subject: feat(ssh): wave 5a — exec-backend remote-backend factory handle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exec-backend declares remoteExecBackendFactoryHandle (a consumer-defined ServiceHandle<(computerId) => ExecBackend>) that the ssh package will provide (standard→core layering). The resolver's computerId-set branch now lazy-looks-up this factory (at tool-execute time, runtime) and calls it; if ssh isn't loaded, getService throws → a clear 'SSH remote execution is not configured' error. The computerId-undefined (local) branch is byte-identical to before. This is the seam wave 5b (the ssh package) plugs into. +tests for both branches. Verified: tsc -b EXIT 0, biome clean. No merge or push. --- packages/exec-backend/src/service.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'packages/exec-backend/src/service.ts') diff --git a/packages/exec-backend/src/service.ts b/packages/exec-backend/src/service.ts index 81ea5fa..6cfa9de 100644 --- a/packages/exec-backend/src/service.ts +++ b/packages/exec-backend/src/service.ts @@ -25,3 +25,22 @@ export type ExecBackendResolver = (computerId?: string) => ExecBackend; * activation by `host-bin`). */ export const execBackendHandle = defineService("exec-backend/resolver"); + +/** + * A factory the `ssh` extension provides: given a computerId (SSH alias), + * returns the remote `ExecBackend`. Absent (ssh not loaded) → remote execution + * is unconfigured. + * + * This is a **consumer-defined handle**: `exec-backend` (a core extension) + * declares it, and the `ssh` extension (a standard extension, built in a later + * wave) `host.provideService`s it. That direction (standard → core, consumer + * defines / provider implements) is the only layering that keeps the kernel free + * of any concrete feature name — `exec-backend` owns the seam, `ssh` plugs in. + * + * The resolver looks this up LAZILY at resolve time (tool-execute time, after + * all extensions have activated), so missing-the-provider degrades gracefully + * rather than crashing activation. + */ +export const remoteExecBackendFactoryHandle = defineService<(computerId: string) => ExecBackend>( + "exec-backend/remote-factory", +); -- cgit v1.2.3