| ... | @@ -47,7 +47,9 @@ const personalSkill = { | ... | @@ -47,7 +47,9 @@ const personalSkill = { |
| 47 | }; | 47 | }; |
| 48 | | 48 | |
| 49 | // Respond through the real stdio transport, with a distinct command catalog for each cwd. | 49 | // Respond through the real stdio transport, with a distinct command catalog for each cwd. |
| 50 | const makePiSpawner = Effect.gen(function* () { | 50 | const makePiSpawner = Effect.fnUntraced(function* ( |
| | 51 | discovery: { readonly state?: unknown; readonly models?: ReadonlyArray<unknown> } = {}, |
| | 52 | ) { |
| 51 | const pendingCommand = yield* Deferred.make<void>(); | 53 | const pendingCommand = yield* Deferred.make<void>(); |
| 52 | const launches: Array<ChildProcess.StandardCommand> = []; | 54 | const launches: Array<ChildProcess.StandardCommand> = []; |
| 53 | const spawner = ChildProcessSpawner.make((command) => | 55 | const spawner = ChildProcessSpawner.make((command) => |
| ... | @@ -92,8 +94,10 @@ const makePiSpawner = Effect.gen(function* () { | ... | @@ -92,8 +94,10 @@ const makePiSpawner = Effect.gen(function* () { |
| 92 | ], | 94 | ], |
| 93 | } | 95 | } |
| 94 | : request.type === "get_available_models" | 96 | : request.type === "get_available_models" |
| 95 | ? { models: [{ provider: "test", id: "model" }] } | 97 | ? { models: discovery.models ?? [{ provider: "test", id: "model" }] } |
| 96 | : {}; | 98 | : request.type === "get_state" |
| | 99 | ? (discovery.state ?? {}) |
| | 100 | : {}; |
| 97 | return Queue.offer( | 101 | return Queue.offer( |
| 98 | stdout, | 102 | stdout, |
| 99 | encoder.encode( | 103 | encoder.encode( |
| ... | @@ -125,7 +129,7 @@ const create = (config: Partial<PiSettings> = {}, enabled = true) => | ... | @@ -125,7 +129,7 @@ const create = (config: Partial<PiSettings> = {}, enabled = true) => |
| 125 | it.layer(layerTest)("PiDriver workspace discovery", (it) => { | 129 | it.layer(layerTest)("PiDriver workspace discovery", (it) => { |
| 126 | it.effect("keeps each workspace's skills and commands separate from the machine catalog", () => | 130 | it.effect("keeps each workspace's skills and commands separate from the machine catalog", () => |
| 127 | Effect.gen(function* () { | 131 | Effect.gen(function* () { |
| 128 | const { spawner, launches } = yield* makePiSpawner; | 132 | const { spawner, launches } = yield* makePiSpawner(); |
| 129 | const instance = yield* create({ launchArgs: '--approve --skill "extra skill"' }).pipe( | 133 | const instance = yield* create({ launchArgs: '--approve --skill "extra skill"' }).pipe( |
| 130 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), | 134 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), |
| 131 | ); | 135 | ); |
| ... | @@ -186,11 +190,50 @@ it.layer(layerTest)("PiDriver workspace discovery", (it) => { | ... | @@ -186,11 +190,50 @@ it.layer(layerTest)("PiDriver workspace discovery", (it) => { |
| 186 | }).pipe(Effect.scoped), | 190 | }).pipe(Effect.scoped), |
| 187 | ); | 191 | ); |
| 188 | | 192 | |
| | 193 | it.effect.each([true, false])( |
| | 194 | "limits discovered thinking defaults to the known active model, known=%s", |
| | 195 | (known) => |
| | 196 | Effect.gen(function* () { |
| | 197 | const { spawner } = yield* makePiSpawner({ |
| | 198 | state: { |
| | 199 | thinkingLevel: "high", |
| | 200 | ...(known ? { model: { provider: "test", id: "model" } } : {}), |
| | 201 | }, |
| | 202 | models: [ |
| | 203 | { provider: "test", id: "model", reasoning: true }, |
| | 204 | { provider: "other", id: "model", reasoning: true }, |
| | 205 | { provider: "test", id: "other", reasoning: true }, |
| | 206 | ], |
| | 207 | }); |
| | 208 | const instance = yield* create().pipe( |
| | 209 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), |
| | 210 | ); |
| | 211 | yield* instance.snapshot.refresh; |
| | 212 | const snapshot = yield* instance.snapshot.getSnapshot; |
| | 213 | assert.deepEqual( |
| | 214 | snapshot.models.map((model) => [ |
| | 215 | model.slug, |
| | 216 | (model.capabilities?.optionDescriptors ?? []).flatMap((descriptor) => |
| | 217 | descriptor.type === "select" |
| | 218 | ? descriptor.options.filter((option) => option.isDefault).map((option) => option.id) |
| | 219 | : [], |
| | 220 | ), |
| | 221 | ]), |
| | 222 | [ |
| | 223 | ["default", []], |
| | 224 | ["test/model", known ? ["high"] : []], |
| | 225 | ["other/model", []], |
| | 226 | ["test/other", []], |
| | 227 | ], |
| | 228 | ); |
| | 229 | }).pipe(Effect.scoped), |
| | 230 | ); |
| | 231 | |
| 189 | it.effect( | 232 | it.effect( |
| 190 | "fails command discovery instead of returning an empty successful workspace catalog", | 233 | "fails command discovery instead of returning an empty successful workspace catalog", |
| 191 | () => | 234 | () => |
| 192 | Effect.gen(function* () { | 235 | Effect.gen(function* () { |
| 193 | const { spawner } = yield* makePiSpawner; | 236 | const { spawner } = yield* makePiSpawner(); |
| 194 | const instance = yield* create().pipe( | 237 | const instance = yield* create().pipe( |
| 195 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), | 238 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), |
| 196 | ); | 239 | ); |
| ... | @@ -208,7 +251,7 @@ it.layer(layerTest)("PiDriver workspace discovery", (it) => { | ... | @@ -208,7 +251,7 @@ it.layer(layerTest)("PiDriver workspace discovery", (it) => { |
| 208 | | 251 | |
| 209 | it.effect("times out workspace discovery that needs interactive input", () => | 252 | it.effect("times out workspace discovery that needs interactive input", () => |
| 210 | Effect.gen(function* () { | 253 | Effect.gen(function* () { |
| 211 | const { spawner, pendingCommand } = yield* makePiSpawner; | 254 | const { spawner, pendingCommand } = yield* makePiSpawner(); |
| 212 | const instance = yield* create().pipe( | 255 | const instance = yield* create().pipe( |
| 213 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), | 256 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), |
| 214 | ); | 257 | ); |