@magnitudedev/pi-extension 0.0.1-alpha.1 → 0.0.1-alpha.2

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.
package/README.md CHANGED
@@ -10,9 +10,15 @@ pi install npm:@magnitudedev/pi-extension
10
10
  ```
11
11
 
12
12
  On the next fresh interactive Pi launch, Magnitude asks **“Set up local models with Magnitude now?”**
13
- Yes sends this prompt to your current Pi agent and starts onboarding:
14
-
15
- > Set up local models for me with the Magnitude CLI. Install it with `npm i -g @magnitudedev/cli` (or my package manager), then run `magnitude docs onboarding` and follow the instructions.
13
+ Yes opens Magnitude's actual graphical setup in the same terminal, including its model rankings,
14
+ radar, downloads, and loading progress. It connects Pi automatically at the final step, then returns
15
+ to the same Pi conversation with the selected model active. No agent prompt or cloud credentials
16
+ are needed. If Magnitude is missing, accepting setup installs the CLI with
17
+ `npm install --global @magnitudedev/cli` before opening onboarding. Pi stays visible with its native
18
+ spinner: “Installing Magnitude…”. Installer output is suppressed; failures
19
+ show a concise diagnostic. Escape cancels preparation, and `/magnitude-setup` retries.
20
+ An existing CLI is preserved and must support hosted setup; an incompatible version reports an
21
+ update requirement rather than being silently replaced.
16
22
 
17
23
  No or Escape leaves “You can set up local models anytime with `/magnitude-setup`.” in the conversation.
18
24
  The offer is remembered per Pi profile across restarts, reloads, and package updates. Existing
@@ -20,9 +26,9 @@ Magnitude model configurations, non-interactive modes, conversations, and startu
20
26
  alone. Run `/magnitude-setup` whenever you want to start onboarding yourself.
21
27
 
22
28
  The package includes the Magnitude usage skill; an already-loaded skill of that name takes
23
- precedence without a collision warning. `--no-skills` disables this fallback too. The CLI is not
24
- an npm dependency and is not required to load the extension. Your Pi agent needs a working model
25
- and credentials to carry out onboarding.
29
+ precedence without a collision warning. `--no-skills` disables this fallback too. No separate CLI
30
+ installation is needed. npm must be available with a writable global prefix, as for a normal npm
31
+ CLI installation. Merely loading the extension does not install software.
26
32
 
27
33
  If you already have Magnitude and a local model, connect directly:
28
34
 
@@ -49,7 +55,7 @@ latency, and token-weighted generation throughput. Pi extensions execute with yo
49
55
 
50
56
  Commands:
51
57
 
52
- - `/magnitude-setup` — ask your current agent to set up Magnitude local models
58
+ - `/magnitude-setup` — open Magnitude's graphical model setup inside Pi
53
59
  - `/load-model [model-id]` — load an installed model
54
60
  - `/stop-model` — stop the active model
55
61
 
@@ -74,3 +80,16 @@ builds and runs the checkout's inference runtime,
74
80
  and keeps the current source CLI available until Pi exits. Exiting Pi stops the development runtime
75
81
  and restores the service state that existed before launch. The launcher inherits the current
76
82
  environment; it does not start or configure tracing.
83
+
84
+ To test the first-run setup offer with no preconfigured Magnitude provider:
85
+
86
+ ```sh
87
+ bun run dev:pi --setup
88
+ ```
89
+
90
+ This installs only the checkout's package into the temporary Pi profile. Accept the setup offer,
91
+ choose a model, and return to Pi to chat. Both development modes keep connection files and skills
92
+ inside the temporary profile, and do not change login-startup registration. They share the machine's
93
+ real model storage and inference service: downloads consume disk space and selected models use
94
+ memory. The launcher restores the prior managed service after Pi exits. Ordinary installed setup
95
+ does enable login startup.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@magnitudedev/pi-extension",
3
- "version": "0.0.1-alpha.1",
3
+ "version": "0.0.1-alpha.2",
4
4
  "rpcVersion": 1,
5
- "contentFingerprint": "292fa6fd784d957591e91f9a67c2460b7cf503149b66cdfe22ecd68ab33ca87d",
5
+ "contentFingerprint": "5661646da7080511725cdef888b7ce04148c99b56fbe6454619754ebc5235718",
6
6
  "files": {
7
- "README.md": "098773e588d568025e90b7aaa716879ddb7e8e2e87492fe86042fce856f66520",
8
- "dist/magnitude.js": "968f6bf0f605a4500cab5e4852edb5f8c67d1d4dd16d0574e13f1ac922d93522",
7
+ "README.md": "0334364928717efd1b146486d6dc2d9ff0f28b77ff28b162d04351738170b581",
8
+ "dist/magnitude.js": "915f1d6bb080180a774b1bd009b3d7bc6c5cbab94fd7ab067dd3345d638538ad",
9
9
  "dist/skills/magnitude/SKILL.md": "37de67f0c7b831415f6298c8785b7ae97d5cfe454dc778651d96114840d2ace2"
10
10
  }
11
11
  }
package/dist/magnitude.js CHANGED
@@ -5842,19 +5842,318 @@ var registerMagnitudeCommands = (pi, sdk = clientLayer2()) => {
5842
5842
  };
5843
5843
 
5844
5844
  // extensions/onboarding.ts
5845
- import * as FileSystem from "@effect/platform/FileSystem";
5845
+ import * as FileSystem3 from "@effect/platform/FileSystem";
5846
5846
  import * as NodeFileSystem2 from "@effect/platform-node/NodeFileSystem";
5847
5847
  import { getAgentDir, parseArgs } from "@earendil-works/pi-coding-agent";
5848
- import { Effect as Effect11, Exit as Exit3, Scope as Scope4 } from "effect";
5848
+ import { Effect as Effect13, Exit as Exit4, Scope as Scope5 } from "effect";
5849
5849
  import { fileURLToPath } from "node:url";
5850
- var SETUP_PROMPT = "Set up local models for me with the Magnitude CLI. Install it with `npm i -g @magnitudedev/cli` (or my package manager), then run `magnitude docs onboarding` and follow the instructions.";
5850
+
5851
+ // extensions/setup.ts
5852
+ import * as Command2 from "@effect/platform/Command";
5853
+ import * as CommandExecutor3 from "@effect/platform/CommandExecutor";
5854
+ import * as FileSystem from "@effect/platform/FileSystem";
5855
+ import * as NodeContext from "@effect/platform-node/NodeContext";
5856
+ import { delimiter, join } from "node:path";
5857
+ import { stripVTControlCharacters } from "node:util";
5858
+ import { Context as Context7, Effect as Effect12, Exit as Exit3, Fiber as Fiber2, Layer as Layer6, ManagedRuntime as ManagedRuntime2, Schema as Schema53, Scope as Scope4, Stream as Stream7 } from "effect";
5859
+ import { CancellableLoader } from "@earendil-works/pi-tui";
5860
+
5861
+ // ../../packages/utils/src/process/interactive-process.ts
5862
+ import { spawn } from "node:child_process";
5863
+ import { Deferred as Deferred3, Duration as Duration2, Effect as Effect11, Option as Option17, Schema as Schema51 } from "effect";
5864
+
5865
+ class InteractiveProcessFailed extends Schema51.TaggedError()("InteractiveProcessFailed", {
5866
+ operation: Schema51.Literal("spawn", "run"),
5867
+ message: Schema51.String
5868
+ }) {
5869
+ }
5870
+ var messageFrom = (cause) => cause instanceof Error ? cause.message : String(cause);
5871
+ var definedEnvironment = (environment) => Object.fromEntries(Object.entries(environment).filter((entry) => entry[1] !== undefined));
5872
+ var acquireInteractiveProcess = (input) => Effect11.gen(function* () {
5873
+ const termination = yield* Deferred3.make();
5874
+ const child = yield* Effect11.async((resume) => {
5875
+ let acquired = false;
5876
+ let handle;
5877
+ try {
5878
+ handle = spawn(input.executable, [...input.args], {
5879
+ cwd: input.workingDirectory,
5880
+ detached: false,
5881
+ env: definedEnvironment(input.environment),
5882
+ shell: false,
5883
+ stdio: "inherit"
5884
+ });
5885
+ } catch (cause) {
5886
+ resume(Effect11.fail(new InteractiveProcessFailed({
5887
+ operation: "spawn",
5888
+ message: messageFrom(cause)
5889
+ })));
5890
+ return;
5891
+ }
5892
+ const onError = (cause) => {
5893
+ const failure = new InteractiveProcessFailed({
5894
+ operation: acquired ? "run" : "spawn",
5895
+ message: messageFrom(cause)
5896
+ });
5897
+ if (acquired) {
5898
+ Deferred3.unsafeDone(termination, Effect11.fail(failure));
5899
+ } else {
5900
+ resume(Effect11.fail(failure));
5901
+ }
5902
+ };
5903
+ const onExit = (code, signal) => {
5904
+ Deferred3.unsafeDone(termination, Effect11.succeed(code === null ? { _tag: "Signaled", signal } : { _tag: "Exited", code }));
5905
+ };
5906
+ const onSpawn = () => {
5907
+ acquired = true;
5908
+ resume(Effect11.succeed(handle));
5909
+ };
5910
+ handle.once("error", onError);
5911
+ handle.once("exit", onExit);
5912
+ handle.once("spawn", onSpawn);
5913
+ return Effect11.sync(() => {
5914
+ if (!acquired) {
5915
+ handle.removeListener("error", onError);
5916
+ handle.removeListener("exit", onExit);
5917
+ handle.removeListener("spawn", onSpawn);
5918
+ if (handle.exitCode === null && handle.signalCode === null) {
5919
+ try {
5920
+ handle.kill("SIGTERM");
5921
+ } catch {}
5922
+ }
5923
+ }
5924
+ });
5925
+ });
5926
+ return { child, termination };
5927
+ });
5928
+ var FORWARDED_SIGNALS = process.platform === "win32" ? ["SIGINT", "SIGTERM", "SIGBREAK"] : ["SIGINT", "SIGTERM", "SIGHUP"];
5929
+ var awaitWithSignalForwarding = ({ child, termination }) => Effect11.acquireUseRelease(Effect11.sync(() => {
5930
+ const listeners = new Map;
5931
+ for (const signal of FORWARDED_SIGNALS) {
5932
+ const listener = () => {
5933
+ try {
5934
+ child.kill(signal);
5935
+ } catch {}
5936
+ };
5937
+ listeners.set(signal, listener);
5938
+ process.on(signal, listener);
5939
+ }
5940
+ return listeners;
5941
+ }), () => Deferred3.await(termination), (listeners) => Effect11.sync(() => {
5942
+ for (const [signal, listener] of listeners) {
5943
+ process.removeListener(signal, listener);
5944
+ }
5945
+ }));
5946
+ var terminateAndReap = ({ child, termination }) => Effect11.gen(function* () {
5947
+ if (yield* Deferred3.isDone(termination))
5948
+ return;
5949
+ yield* Effect11.sync(() => {
5950
+ try {
5951
+ child.kill("SIGTERM");
5952
+ } catch {}
5953
+ });
5954
+ const graceful = yield* Deferred3.await(termination).pipe(Effect11.ignore, Effect11.timeoutOption(Duration2.seconds(2)));
5955
+ if (Option17.isSome(graceful))
5956
+ return;
5957
+ yield* Effect11.sync(() => {
5958
+ try {
5959
+ child.kill("SIGKILL");
5960
+ } catch {}
5961
+ });
5962
+ yield* Deferred3.await(termination).pipe(Effect11.ignore, Effect11.timeout(Duration2.seconds(2)), Effect11.ignore);
5963
+ });
5964
+ var runInteractiveProcess = (input) => Effect11.acquireUseRelease(acquireInteractiveProcess(input), awaitWithSignalForwarding, terminateAndReap);
5965
+ // ../../packages/client-common/src/harness-connections/hosted-setup.ts
5966
+ import { Schema as Schema52 } from "effect";
5967
+ var HOSTED_SETUP_PROTOCOL_VERSION = 1;
5968
+ var HOSTED_SETUP_MAX_RESULT_BYTES = 16 * 1024;
5969
+ var HostedSetupCapability = Schema52.Struct({
5970
+ protocolVersion: Schema52.Literal(HOSTED_SETUP_PROTOCOL_VERSION)
5971
+ });
5972
+ var version = Schema52.Literal(HOSTED_SETUP_PROTOCOL_VERSION);
5973
+ var HostedSetupResult = Schema52.Union(Schema52.TaggedStruct("Completed", { protocolVersion: version, modelId: ModelIdSchema }), Schema52.TaggedStruct("Cancelled", { protocolVersion: version }), Schema52.TaggedStruct("Failed", {
5974
+ protocolVersion: version,
5975
+ message: Schema52.String.pipe(Schema52.filter((message) => new TextEncoder().encode(message).length <= 4096))
5976
+ }));
5977
+
5978
+ // extensions/setup.ts
5979
+ class PiSetupFailed extends Schema53.TaggedError()("PiSetupFailed", {
5980
+ message: Schema53.String
5981
+ }) {
5982
+ }
5983
+ var failure = (message) => new PiSetupFailed({ message });
5984
+ var prepareMagnitudeCli = (cwd, setMessage = () => Effect12.void) => Effect12.gen(function* () {
5985
+ const fs = yield* FileSystem.FileSystem;
5986
+ const override = process.env.MAGNITUDE_CLI?.trim();
5987
+ const executable = override || "magnitude";
5988
+ const probe = Effect12.scoped(Effect12.gen(function* () {
5989
+ const child = yield* Command2.make(executable, "setup", "--host-protocol").pipe(Command2.start);
5990
+ const [code, output, stderr] = yield* Effect12.all([
5991
+ child.exitCode,
5992
+ child.stdout.pipe(Stream7.decodeText(), Stream7.runFold("", (text2, part) => (text2 + part).slice(0, 4097))),
5993
+ child.stderr.pipe(Stream7.decodeText(), Stream7.runFold("", (text2, part) => (text2 + part).slice(-4096)))
5994
+ ], { concurrency: "unbounded" });
5995
+ if (code !== 0 || output.length > 4096)
5996
+ return yield* failure(`Magnitude's setup capability check failed at ${executable} (exit ${code}). ${stripVTControlCharacters(stderr).trim().slice(-600)}${override ? " Check MAGNITUDE_CLI." : ""}`);
5997
+ return output;
5998
+ }));
5999
+ const capability = yield* probe.pipe(Effect12.catchIf((error) => !override && error._tag === "SystemError" && error.reason === "NotFound", (error) => Effect12.gen(function* () {
6000
+ for (const directory of (process.env.PATH ?? "").split(delimiter)) {
6001
+ if (yield* fs.exists(join(directory || cwd, executable)))
6002
+ return yield* error;
6003
+ }
6004
+ yield* setMessage("Installing Magnitude…");
6005
+ yield* Effect12.scoped(Effect12.gen(function* () {
6006
+ const child = yield* Command2.make("npm", "install", "--global", "@magnitudedev/cli").pipe(Command2.workingDirectory(cwd), Command2.start);
6007
+ const [code, , stderr] = yield* Effect12.all([
6008
+ child.exitCode,
6009
+ Stream7.runDrain(child.stdout),
6010
+ child.stderr.pipe(Stream7.decodeText(), Stream7.runFold("", (text2, part) => (text2 + part).slice(-4096)))
6011
+ ], { concurrency: "unbounded" });
6012
+ if (code !== 0)
6013
+ return yield* failure(`Magnitude installation failed (exit ${code}). ${stripVTControlCharacters(stderr).trim().slice(-600)} Run /magnitude-setup to retry.`);
6014
+ }));
6015
+ return yield* probe;
6016
+ })), Effect12.timeout("10 minutes"), Effect12.mapError((error) => error instanceof PiSetupFailed ? error : failure(`Could not prepare Magnitude: ${String(error)}. Run /magnitude-setup to retry${override ? ", or check MAGNITUDE_CLI" : ""}.`)));
6017
+ yield* Schema53.decodeUnknown(Schema53.parseJson(HostedSetupCapability))(capability).pipe(Effect12.mapError(() => failure(`The Magnitude CLI at ${executable} does not support hosted setup. Update @magnitudedev/cli${override ? ", or check MAGNITUDE_CLI" : ""}.`)));
6018
+ return executable;
6019
+ });
6020
+ var withPiPreparation = (ctx, work) => Effect12.acquireUseRelease(Effect12.async((resume, signal) => {
6021
+ let closed;
6022
+ closed = ctx.ui.custom((tui, theme, _keys, done) => {
6023
+ const loader = new CancellableLoader(tui, (text2) => theme.fg("accent", text2), (text2) => theme.fg("muted", text2), "Installing Magnitude…");
6024
+ if (signal.aborted) {
6025
+ loader.dispose();
6026
+ done();
6027
+ } else
6028
+ resume(Effect12.succeed({ loader, finish: () => done(), closed: () => closed }));
6029
+ return loader;
6030
+ });
6031
+ closed.catch((error) => resume(Effect12.fail(failure(`Could not open Pi setup: ${String(error)}`))));
6032
+ }), ({ loader }) => work((message) => Effect12.sync(() => loader.setMessage(message))).pipe(Effect12.raceFirst(Effect12.async((resume) => {
6033
+ loader.onAbort = () => resume(Effect12.fail(failure("Magnitude setup cancelled. Run /magnitude-setup to retry.")));
6034
+ if (loader.signal.aborted)
6035
+ loader.onAbort();
6036
+ return Effect12.sync(() => {
6037
+ loader.onAbort = undefined;
6038
+ });
6039
+ }))), ({ loader, finish, closed }) => Effect12.sync(() => {
6040
+ loader.dispose();
6041
+ finish();
6042
+ }).pipe(Effect12.zipRight(Effect12.promise(closed))));
6043
+ var restoreHostTerminal = (tui) => tui.terminal.write("\x1B[?2026l\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?1004l" + "\x1B[?2004l\x1B[>4;0m\x1B[=0u\x1B[?1049l\x1B[0m\x1B[0 q");
6044
+ var withPiTerminal = (ctx, work) => Effect12.acquireUseRelease(Effect12.async((resume, signal) => {
6045
+ let closed;
6046
+ closed = ctx.ui.custom((tui, _theme, _keys, done) => {
6047
+ if (signal.aborted)
6048
+ done();
6049
+ else
6050
+ resume(Effect12.succeed({ tui, finish: () => done(), closed: () => closed }));
6051
+ return { render: () => [], invalidate: () => {} };
6052
+ });
6053
+ closed.catch((error) => resume(Effect12.fail(failure(`Could not open Pi setup: ${String(error)}`))));
6054
+ }), ({ tui }) => Effect12.sync(() => tui.stop()).pipe(Effect12.zipRight(work)), ({ tui, finish, closed }) => Effect12.sync(() => {
6055
+ try {
6056
+ restoreHostTerminal(tui);
6057
+ tui.start();
6058
+ tui.requestRender(true);
6059
+ } finally {
6060
+ finish();
6061
+ }
6062
+ }).pipe(Effect12.zipRight(Effect12.promise(closed))));
6063
+ var validateSetupTermination = (result, termination) => {
6064
+ if (termination._tag !== "Exited" || termination.code === 0 !== (result._tag !== "Failed")) {
6065
+ return Effect12.fail(failure("Magnitude setup exited without a consistent completion result. Run /magnitude-setup to retry."));
6066
+ }
6067
+ return result._tag === "Failed" ? Effect12.fail(failure(result.message)) : Effect12.succeed(result);
6068
+ };
6069
+ var PiSetup = Context7.GenericTag("pi/PiSetup");
6070
+ var PiSetupLive = Layer6.effect(PiSetup, Effect12.gen(function* () {
6071
+ const fs = yield* FileSystem.FileSystem;
6072
+ const executor = yield* CommandExecutor3.CommandExecutor;
6073
+ return {
6074
+ run: (ctx) => Effect12.scoped(Effect12.gen(function* () {
6075
+ const directory = yield* fs.makeTempDirectoryScoped({ prefix: "magnitude-pi-setup-" });
6076
+ const resultPath = `${directory}/result.json`;
6077
+ const executable = yield* withPiPreparation(ctx, (setMessage) => prepareMagnitudeCli(ctx.cwd, setMessage));
6078
+ const termination = yield* withPiTerminal(ctx, runInteractiveProcess({
6079
+ executable,
6080
+ args: ["setup", "--host", "pi", "--result-file", resultPath],
6081
+ environment: process.env,
6082
+ workingDirectory: ctx.cwd
6083
+ }));
6084
+ if (termination._tag === "Signaled" && termination.signal === "SIGINT") {
6085
+ return { protocolVersion: HOSTED_SETUP_PROTOCOL_VERSION, _tag: "Cancelled" };
6086
+ }
6087
+ if (termination._tag === "Signaled") {
6088
+ return yield* failure(`Magnitude setup stopped unexpectedly (${termination.signal}). Run /magnitude-setup to retry.`);
6089
+ }
6090
+ const stat = yield* fs.stat(resultPath).pipe(Effect12.mapError(() => failure("Magnitude setup exited without a completion result. Run /magnitude-setup to retry.")));
6091
+ if (stat.type !== "File" || stat.size > BigInt(HOSTED_SETUP_MAX_RESULT_BYTES)) {
6092
+ return yield* failure("Magnitude setup returned an invalid or oversized result");
6093
+ }
6094
+ const result = yield* fs.readFileString(resultPath).pipe(Effect12.flatMap(Schema53.decodeUnknown(Schema53.parseJson(HostedSetupResult))), Effect12.mapError(() => failure("Magnitude setup did not return a valid completion result. Run /magnitude-setup to retry.")));
6095
+ return yield* validateSetupTermination(result, termination);
6096
+ })).pipe(Effect12.provideService(CommandExecutor3.CommandExecutor, executor), Effect12.provideService(FileSystem.FileSystem, fs), Effect12.mapError((error) => error instanceof PiSetupFailed ? error : failure(`Magnitude setup could not finish: ${String(error)}`)))
6097
+ };
6098
+ }));
6099
+ var registerMagnitudeSetup = (pi, layer4 = PiSetupLive.pipe(Layer6.provide(NodeContext.layer))) => {
6100
+ const runtime = ManagedRuntime2.make(layer4);
6101
+ const scope = Effect12.runSync(Scope4.make());
6102
+ const gate = Effect12.runSync(Effect12.makeSemaphore(1));
6103
+ const action = (ctx) => Effect12.gen(function* () {
6104
+ if (ctx.mode !== "tui")
6105
+ return yield* failure("Run /magnitude-setup in Pi's interactive terminal.");
6106
+ if (!ctx.isIdle() || ctx.hasPendingMessages())
6107
+ return yield* failure("Wait for the current task to finish, then run /magnitude-setup.");
6108
+ const setup = yield* PiSetup;
6109
+ const result = yield* setup.run(ctx);
6110
+ if (result._tag !== "Completed")
6111
+ return false;
6112
+ yield* Effect12.tryPromise({
6113
+ try: async () => {
6114
+ await ctx.modelRegistry.refresh();
6115
+ const model2 = ctx.modelRegistry.find("magnitude", result.modelId);
6116
+ if (!model2 || !await pi.setModel(model2))
6117
+ throw new Error("The selected model is not available in Pi");
6118
+ },
6119
+ catch: (error) => failure(`Magnitude setup completed, but Pi could not activate the model: ${String(error)}. Run /reload and select it with /model.`)
6120
+ });
6121
+ return true;
6122
+ });
6123
+ const run = (ctx) => runtime.runPromise(Effect12.forkIn(gate.withPermitsIfAvailable(1)(action(ctx)).pipe(Effect12.flatMap((result) => result._tag === "Some" ? Effect12.succeed(result.value) : Effect12.fail(failure("Magnitude setup is already open."))), Effect12.catchAll((error) => Effect12.sync(() => {
6124
+ ctx.ui.notify(error.message, "error");
6125
+ return false;
6126
+ }))), scope).pipe(Effect12.flatMap(Fiber2.join)));
6127
+ pi.registerCommand("magnitude-setup", {
6128
+ description: "Choose and set up a local Magnitude model",
6129
+ handler: async (_args, ctx) => {
6130
+ const reload = await run(ctx);
6131
+ if (reload) {
6132
+ try {
6133
+ await ctx.reload();
6134
+ } catch (error) {
6135
+ throw failure(`Magnitude setup completed and selected the model, but Pi could not reload its resources: ${String(error)}. Run /reload to retry.`);
6136
+ }
6137
+ }
6138
+ }
6139
+ });
6140
+ return {
6141
+ run,
6142
+ dispose: async () => {
6143
+ await Effect12.runPromise(Scope4.close(scope, Exit3.void));
6144
+ await runtime.dispose();
6145
+ }
6146
+ };
6147
+ };
6148
+
6149
+ // extensions/onboarding.ts
5851
6150
  var SETUP_QUESTION = "Set up local models with Magnitude now?";
5852
6151
  var SETUP_REMINDER = "You can set up local models anytime with `/magnitude-setup`.";
5853
- var claimSetupOffer = (agentDir) => Effect11.gen(function* () {
5854
- const fs = yield* FileSystem.FileSystem;
6152
+ var claimSetupOffer = (agentDir) => Effect13.gen(function* () {
6153
+ const fs = yield* FileSystem3.FileSystem;
5855
6154
  const directory = `${agentDir}/magnitude`;
5856
6155
  yield* fs.makeDirectory(directory, { recursive: true });
5857
- return yield* fs.writeFileString(`${directory}/setup-offered`, "", { flag: "wx" }).pipe(Effect11.as(true), Effect11.catchTag("SystemError", (error) => error.reason === "AlreadyExists" ? Effect11.succeed(false) : Effect11.fail(error)));
6156
+ return yield* fs.writeFileString(`${directory}/setup-offered`, "", { flag: "wx" }).pipe(Effect13.as(true), Effect13.catchTag("SystemError", (error) => error.reason === "AlreadyExists" ? Effect13.succeed(false) : Effect13.fail(error)));
5858
6157
  });
5859
6158
  function canOfferSetup(ctx, argv) {
5860
6159
  if (ctx.mode !== "tui" || !ctx.isIdle() || ctx.hasPendingMessages() || ctx.ui.getEditorText().trim())
@@ -5866,30 +6165,21 @@ function canOfferSetup(ctx, argv) {
5866
6165
  const args = parseArgs([...argv]);
5867
6166
  return args.messages.length === 0 && args.fileArgs.length === 0;
5868
6167
  }
5869
- var offerSetup = (pi, ctx, agentDir, signal) => Effect11.gen(function* () {
6168
+ var offerSetup = (pi, ctx, agentDir, signal, runSetup) => Effect13.gen(function* () {
5870
6169
  if (!(yield* claimSetupOffer(agentDir)) || signal.aborted)
5871
6170
  return;
5872
- const accepted = yield* Effect11.tryPromise(() => ctx.ui.confirm(SETUP_QUESTION, "", { signal }));
6171
+ const accepted = yield* Effect13.tryPromise(() => ctx.ui.confirm(SETUP_QUESTION, "", { signal }));
5873
6172
  if (signal.aborted)
5874
6173
  return;
5875
- if (accepted && ctx.isIdle() && !ctx.hasPendingMessages())
5876
- pi.sendUserMessage(SETUP_PROMPT);
5877
- else
6174
+ if (accepted && ctx.isIdle() && !ctx.hasPendingMessages()) {
6175
+ yield* Effect13.tryPromise(() => runSetup(ctx));
6176
+ } else
5878
6177
  pi.sendMessage({ customType: "magnitude-setup", content: SETUP_REMINDER, display: true });
5879
6178
  });
5880
6179
  function registerMagnitudeOnboarding(pi) {
5881
6180
  const abort = new AbortController;
5882
- const scope = Effect11.runSync(Scope4.make());
5883
- pi.registerCommand("magnitude-setup", {
5884
- description: "Set up local models with Magnitude",
5885
- handler: async (_args, ctx) => {
5886
- if (!ctx.isIdle() || ctx.hasPendingMessages()) {
5887
- ctx.ui.notify("Wait for the current task to finish, then run /magnitude-setup.", "warning");
5888
- return;
5889
- }
5890
- pi.sendUserMessage(SETUP_PROMPT);
5891
- }
5892
- });
6181
+ const scope = Effect13.runSync(Scope5.make());
6182
+ const setup = registerMagnitudeSetup(pi);
5893
6183
  pi.on("resources_discover", () => {
5894
6184
  if (parseArgs(process.argv.slice(2)).noSkills || pi.getCommands().some((command) => command.source === "skill" && command.name === "skill:magnitude"))
5895
6185
  return;
@@ -5898,24 +6188,25 @@ function registerMagnitudeOnboarding(pi) {
5898
6188
  pi.on("session_start", (event, ctx) => {
5899
6189
  if (event.reason !== "startup" || !canOfferSetup(ctx, process.argv.slice(2)))
5900
6190
  return;
5901
- Effect11.runFork(Effect11.forkIn(offerSetup(pi, ctx, getAgentDir(), abort.signal).pipe(Effect11.provide(NodeFileSystem2.layer), Effect11.catchAll(() => Effect11.sync(() => ctx.ui.notify(`Magnitude setup could not open. ${SETUP_REMINDER}`, "warning")))), scope));
6191
+ Effect13.runFork(Effect13.forkIn(offerSetup(pi, ctx, getAgentDir(), abort.signal, setup.run).pipe(Effect13.provide(NodeFileSystem2.layer), Effect13.catchAll(() => Effect13.sync(() => ctx.ui.notify(`Magnitude setup could not open. ${SETUP_REMINDER}`, "warning")))), scope));
5902
6192
  });
5903
- return () => {
6193
+ return async () => {
5904
6194
  abort.abort();
5905
- return Effect11.runPromise(Scope4.close(scope, Exit3.void));
6195
+ await Effect13.runPromise(Scope5.close(scope, Exit4.void));
6196
+ await setup.dispose();
5906
6197
  };
5907
6198
  }
5908
6199
 
5909
6200
  // extensions/observing-fetch.ts
5910
- import { Effect as Effect12, Either as Either3, Schema as Schema52 } from "effect";
6201
+ import { Effect as Effect14, Either as Either3, Schema as Schema55 } from "effect";
5911
6202
 
5912
6203
  // extensions/protocol.ts
5913
- import { Either as Either2, Schema as Schema51 } from "effect";
5914
- var ProgressChunkSchema = Schema51.Struct({ progress: MagnitudeProgressSchema });
5915
- var TimingsChunkSchema = Schema51.Struct({ timings: MagnitudeTimingsSchema });
6204
+ import { Either as Either2, Schema as Schema54 } from "effect";
6205
+ var ProgressChunkSchema = Schema54.Struct({ progress: MagnitudeProgressSchema });
6206
+ var TimingsChunkSchema = Schema54.Struct({ timings: MagnitudeTimingsSchema });
5916
6207
  var decodeMagnitudeObservation = (value) => {
5917
- const progress = Schema51.decodeUnknownEither(ProgressChunkSchema)(value);
5918
- const timings = Schema51.decodeUnknownEither(TimingsChunkSchema)(value);
6208
+ const progress = Schema54.decodeUnknownEither(ProgressChunkSchema)(value);
6209
+ const timings = Schema54.decodeUnknownEither(TimingsChunkSchema)(value);
5919
6210
  if (Either2.isLeft(progress) && Either2.isLeft(timings))
5920
6211
  return;
5921
6212
  return {
@@ -5926,7 +6217,7 @@ var decodeMagnitudeObservation = (value) => {
5926
6217
 
5927
6218
  // extensions/observing-fetch.ts
5928
6219
  var MAGNITUDE_PROGRESS_HEADER = "Magnitude-Include-Progress";
5929
- var JsonDocumentSchema = Schema52.parseJson(Schema52.Unknown);
6220
+ var JsonDocumentSchema = Schema55.parseJson(Schema55.Unknown);
5930
6221
 
5931
6222
  class SseDataParser {
5932
6223
  #buffer = "";
@@ -5973,26 +6264,26 @@ class SseDataParser {
5973
6264
  this.#dataLines = [];
5974
6265
  if (data === "[DONE]")
5975
6266
  return;
5976
- const decoded = Schema52.decodeUnknownEither(JsonDocumentSchema)(data);
6267
+ const decoded = Schema55.decodeUnknownEither(JsonDocumentSchema)(data);
5977
6268
  if (Either3.isRight(decoded))
5978
6269
  observe(decoded.right);
5979
6270
  }
5980
6271
  }
5981
- var observeResponse = (response, request, signal) => Effect12.scoped(Effect12.gen(function* () {
6272
+ var observeResponse = (response, request, signal) => Effect14.scoped(Effect14.gen(function* () {
5982
6273
  if (!response.ok || response.body === null) {
5983
6274
  yield* request.fail;
5984
6275
  return;
5985
6276
  }
5986
- const reader = yield* Effect12.acquireRelease(Effect12.sync(() => response.body.getReader()), (reader2) => Effect12.promise(() => reader2.cancel()).pipe(Effect12.interruptible, Effect12.timeout("100 millis"), Effect12.ignore, Effect12.ensuring(Effect12.sync(() => reader2.releaseLock()))));
6277
+ const reader = yield* Effect14.acquireRelease(Effect14.sync(() => response.body.getReader()), (reader2) => Effect14.promise(() => reader2.cancel()).pipe(Effect14.interruptible, Effect14.timeout("100 millis"), Effect14.ignore, Effect14.ensuring(Effect14.sync(() => reader2.releaseLock()))));
5987
6278
  if (signal.aborted) {
5988
6279
  yield* request.fail;
5989
6280
  return;
5990
6281
  }
5991
6282
  const decoder = new TextDecoder;
5992
6283
  const parser = new SseDataParser;
5993
- const drain = Effect12.gen(function* () {
6284
+ const drain = Effect14.gen(function* () {
5994
6285
  while (true) {
5995
- const result = yield* Effect12.tryPromise(() => reader.read());
6286
+ const result = yield* Effect14.tryPromise(() => reader.read());
5996
6287
  if (result.done)
5997
6288
  break;
5998
6289
  const values = [];
@@ -6005,35 +6296,35 @@ var observeResponse = (response, request, signal) => Effect12.scoped(Effect12.ge
6005
6296
  }
6006
6297
  yield* request.finish;
6007
6298
  });
6008
- const aborted = Effect12.async((resume) => {
6009
- const abort = () => resume(Effect12.interrupt);
6299
+ const aborted = Effect14.async((resume) => {
6300
+ const abort = () => resume(Effect14.interrupt);
6010
6301
  signal.addEventListener("abort", abort, { once: true });
6011
6302
  if (signal.aborted)
6012
6303
  abort();
6013
- return Effect12.sync(() => signal.removeEventListener("abort", abort));
6304
+ return Effect14.sync(() => signal.removeEventListener("abort", abort));
6014
6305
  });
6015
- yield* Effect12.raceFirst(drain, aborted).pipe(Effect12.onError(() => request.fail));
6016
- })).pipe(Effect12.catchAllCause(() => Effect12.void));
6306
+ yield* Effect14.raceFirst(drain, aborted).pipe(Effect14.onError(() => request.fail));
6307
+ })).pipe(Effect14.catchAllCause(() => Effect14.void));
6017
6308
  var makeObservingFetch = (fetchImplementation, begin, scope) => {
6018
6309
  const observingFetch = async (input, init) => {
6019
6310
  const request = new Request(input, init);
6020
6311
  request.headers.set(MAGNITUDE_PROGRESS_HEADER, "true");
6021
- const progress = Effect12.runSync(Effect12.suspend(begin).pipe(Effect12.catchAllCause(() => Effect12.succeed({
6022
- observe: () => Effect12.void,
6023
- finish: Effect12.void,
6024
- fail: Effect12.void
6312
+ const progress = Effect14.runSync(Effect14.suspend(begin).pipe(Effect14.catchAllCause(() => Effect14.succeed({
6313
+ observe: () => Effect14.void,
6314
+ finish: Effect14.void,
6315
+ fail: Effect14.void
6025
6316
  }))));
6026
6317
  try {
6027
6318
  const response = await fetchImplementation(request);
6028
6319
  try {
6029
6320
  const observation = observeResponse(response.clone(), progress, request.signal);
6030
- Effect12.runFork(Effect12.forkIn(observation, scope));
6321
+ Effect14.runFork(Effect14.forkIn(observation, scope));
6031
6322
  } catch {
6032
- Effect12.runSync(progress.fail.pipe(Effect12.catchAllCause(() => Effect12.void)));
6323
+ Effect14.runSync(progress.fail.pipe(Effect14.catchAllCause(() => Effect14.void)));
6033
6324
  }
6034
6325
  return response;
6035
6326
  } catch (error) {
6036
- Effect12.runSync(progress.fail.pipe(Effect12.catchAllCause(() => Effect12.void)));
6327
+ Effect14.runSync(progress.fail.pipe(Effect14.catchAllCause(() => Effect14.void)));
6037
6328
  throw error;
6038
6329
  }
6039
6330
  };
@@ -6044,9 +6335,9 @@ var makeObservingFetch = (fetchImplementation, begin, scope) => {
6044
6335
 
6045
6336
  // extensions/progress.ts
6046
6337
  import { Text } from "@earendil-works/pi-tui";
6047
- import { Data as Data3, Effect as Effect13, Fiber as Fiber2, Option as Option17, Queue, Schema as Schema53 } from "effect";
6338
+ import { Data as Data3, Effect as Effect15, Fiber as Fiber3, Option as Option18, Queue, Schema as Schema56 } from "effect";
6048
6339
  var MAGNITUDE_SUMMARY_WIDGET_KEY = "magnitude-inference-summary";
6049
- var RequestId = Schema53.Number.pipe(Schema53.int(), Schema53.brand("ProgressRequestId"));
6340
+ var RequestId = Schema56.Number.pipe(Schema56.int(), Schema56.brand("ProgressRequestId"));
6050
6341
 
6051
6342
  class Observing extends Data3.TaggedClass("Observing") {
6052
6343
  }
@@ -6101,31 +6392,31 @@ var formatLiveProgress = ({ progress, modelName, startedAt }, now) => {
6101
6392
  }
6102
6393
  }
6103
6394
  };
6104
- var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(function* () {
6395
+ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(function* () {
6105
6396
  let state = new Idle2;
6106
6397
  let nextId = 0;
6107
6398
  let active;
6108
6399
  let latest;
6109
6400
  let nextResponseId = 0;
6110
6401
  const wake = yield* Queue.sliding(1);
6111
- const present = (f) => Effect13.sync(f).pipe(Effect13.catchAllCause(() => Effect13.void));
6402
+ const present = (f) => Effect15.sync(f).pipe(Effect15.catchAllCause(() => Effect15.void));
6112
6403
  const clearSummary = present(() => ui.setWidget(MAGNITUDE_SUMMARY_WIDGET_KEY, undefined));
6113
6404
  const resetRow = present(() => ui.setWorkingMessage());
6114
6405
  const render2 = present(() => {
6115
6406
  if (active)
6116
6407
  ui.setWorkingMessage(formatLiveProgress(active.phase, now()));
6117
6408
  });
6118
- const finalize = Effect13.gen(function* () {
6409
+ const finalize = Effect15.gen(function* () {
6119
6410
  if (state._tag !== "Settled")
6120
6411
  return;
6121
- if ([...state.run.responses.values()].some(Option17.isNone))
6412
+ if ([...state.run.responses.values()].some(Option18.isNone))
6122
6413
  return;
6123
6414
  if ([...state.run.requests.values()].some((r) => r._tag === "Observing"))
6124
6415
  return;
6125
6416
  const settled = state;
6126
6417
  state = runMachine.transition(settled, "Idle", {});
6127
6418
  const timings = [...settled.run.completed.entries()].filter(([id]) => settled.run.accepted.has(id)).sort(([a], [b]) => a - b).map(([, value]) => value);
6128
- if ([...settled.run.responses.values()].some((outcome) => !Option17.getOrElse(outcome, () => false)) || timings.length === 0) {
6419
+ if ([...settled.run.responses.values()].some((outcome) => !Option18.getOrElse(outcome, () => false)) || timings.length === 0) {
6129
6420
  yield* clearSummary;
6130
6421
  return;
6131
6422
  }
@@ -6134,7 +6425,7 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6134
6425
  const summary = `● ${settled.run.modelName} worked for ${duration(settled.settledAt - settled.run.startedAt)}` + ` · ${seconds(timings[0].time_to_first_token_ms)} TTFT` + (decodeMs > 0 && tokens > 0 ? ` · ${(tokens * 1000 / decodeMs).toFixed(1)} tok/s` : "");
6135
6426
  yield* present(() => ui.setWidget(MAGNITUDE_SUMMARY_WIDGET_KEY, (_tui, theme) => new Text(theme.fg("muted", summary), 0, 0)));
6136
6427
  });
6137
- const clear = Effect13.gen(function* () {
6428
+ const clear = Effect15.gen(function* () {
6138
6429
  if (state._tag === "Disposed")
6139
6430
  return;
6140
6431
  if (state._tag !== "Idle")
@@ -6144,7 +6435,7 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6144
6435
  yield* resetRow;
6145
6436
  yield* clearSummary;
6146
6437
  });
6147
- const startRun = (modelName) => Effect13.gen(function* () {
6438
+ const startRun = (modelName) => Effect15.gen(function* () {
6148
6439
  if (state._tag === "Disposed")
6149
6440
  return;
6150
6441
  if (state._tag === "Settled")
@@ -6154,38 +6445,38 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6154
6445
  state = runMachine.transition(state, "Working", { run: { startedAt: now(), modelName, requests: new Map, completed: new Map, responses: new Map, accepted: new Set } });
6155
6446
  yield* clearSummary;
6156
6447
  });
6157
- const timer = yield* Effect13.forever(Effect13.gen(function* () {
6448
+ const timer = yield* Effect15.forever(Effect15.gen(function* () {
6158
6449
  yield* Queue.take(wake);
6159
6450
  while (active) {
6160
- yield* Effect13.sleep("100 millis");
6451
+ yield* Effect15.sleep("100 millis");
6161
6452
  yield* render2;
6162
6453
  }
6163
- })).pipe(Effect13.forkScoped);
6164
- yield* Effect13.addFinalizer(() => Effect13.gen(function* () {
6454
+ })).pipe(Effect15.forkScoped);
6455
+ yield* Effect15.addFinalizer(() => Effect15.gen(function* () {
6165
6456
  yield* clear;
6166
6457
  if (state._tag !== "Disposed")
6167
6458
  state = runMachine.transition(state, "Disposed", {});
6168
- yield* Fiber2.interrupt(timer);
6459
+ yield* Fiber3.interrupt(timer);
6169
6460
  }));
6170
6461
  return {
6171
6462
  startRun,
6172
6463
  clear,
6173
- settleRun: Effect13.gen(function* () {
6464
+ settleRun: Effect15.gen(function* () {
6174
6465
  if (state._tag === "Working")
6175
6466
  state = runMachine.transition(state, "Settled", { settledAt: now() });
6176
6467
  yield* finalize;
6177
6468
  }),
6178
- beginResponse: (modelName) => Effect13.gen(function* () {
6469
+ beginResponse: (modelName) => Effect15.gen(function* () {
6179
6470
  yield* startRun(modelName);
6180
6471
  const run = state._tag === "Working" ? state.run : undefined;
6181
6472
  const responseId = ++nextResponseId;
6182
6473
  const requests = [];
6183
- run?.responses.set(responseId, Option17.none());
6474
+ run?.responses.set(responseId, Option18.none());
6184
6475
  const belongs = () => run !== undefined && (state._tag === "Working" || state._tag === "Settled") && state.run === run;
6185
- const end = (successful) => Effect13.gen(function* () {
6186
- if (!belongs() || Option17.isSome(run.responses.get(responseId)))
6476
+ const end = (successful) => Effect15.gen(function* () {
6477
+ if (!belongs() || Option18.isSome(run.responses.get(responseId)))
6187
6478
  return;
6188
- run.responses.set(responseId, Option17.some(successful));
6479
+ run.responses.set(responseId, Option18.some(successful));
6189
6480
  const last = requests.at(-1);
6190
6481
  if (successful && last !== undefined)
6191
6482
  run.accepted.add(last);
@@ -6204,16 +6495,16 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6204
6495
  }
6205
6496
  yield* finalize;
6206
6497
  });
6207
- const begin = Effect13.gen(function* () {
6208
- if (!belongs() || Option17.isSome(run.responses.get(responseId)))
6209
- return { observe: () => Effect13.void, finish: Effect13.void, fail: Effect13.void };
6498
+ const begin = Effect15.gen(function* () {
6499
+ if (!belongs() || Option18.isSome(run.responses.get(responseId)))
6500
+ return { observe: () => Effect15.void, finish: Effect15.void, fail: Effect15.void };
6210
6501
  const id = RequestId.make(++nextId);
6211
6502
  requests.push(id);
6212
6503
  latest = id;
6213
6504
  active = undefined;
6214
- run?.requests.set(id, new Observing({ timings: Option17.none() }));
6505
+ run?.requests.set(id, new Observing({ timings: Option18.none() }));
6215
6506
  yield* resetRow;
6216
- const close = (failed) => Effect13.gen(function* () {
6507
+ const close = (failed) => Effect15.gen(function* () {
6217
6508
  if (!belongs())
6218
6509
  return;
6219
6510
  const request = run.requests.get(id);
@@ -6223,7 +6514,7 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6223
6514
  run.requests.set(id, requestMachine.transition(request, "Closed", {}));
6224
6515
  else {
6225
6516
  run.requests.set(id, requestMachine.transition(request, "Observed", {}));
6226
- if (Option17.isSome(request.timings))
6517
+ if (Option18.isSome(request.timings))
6227
6518
  run.completed.set(id, request.timings.value);
6228
6519
  }
6229
6520
  if (latest === id) {
@@ -6233,14 +6524,14 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6233
6524
  yield* finalize;
6234
6525
  });
6235
6526
  return {
6236
- observe: (observation) => Effect13.gen(function* () {
6527
+ observe: (observation) => Effect15.gen(function* () {
6237
6528
  if (!belongs())
6238
6529
  return;
6239
6530
  const request = run.requests.get(id);
6240
6531
  if (request._tag !== "Observing")
6241
6532
  return;
6242
6533
  if (observation.timings)
6243
- run.requests.set(id, requestMachine.hold(request, { timings: Option17.some(observation.timings) }));
6534
+ run.requests.set(id, requestMachine.hold(request, { timings: Option18.some(observation.timings) }));
6244
6535
  if (latest !== id || !observation.progress)
6245
6536
  return;
6246
6537
  const progress = observation.progress;
@@ -6264,35 +6555,35 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect13.gen(fu
6264
6555
  });
6265
6556
 
6266
6557
  // extensions/magnitude.ts
6267
- import { Effect as Effect14, Exit as Exit4, Scope as Scope6 } from "effect";
6558
+ import { Effect as Effect16, Exit as Exit5, Scope as Scope7 } from "effect";
6268
6559
  function magnitudeExtension(pi) {
6269
6560
  const completions = openAICompletionsApi();
6270
6561
  let tracker;
6271
6562
  let scope;
6272
6563
  const disposeCommands = registerMagnitudeCommands(pi);
6273
6564
  const disposeOnboarding = registerMagnitudeOnboarding(pi);
6274
- const perform = (effect) => Effect14.runSync((effect ?? Effect14.void).pipe(Effect14.catchAllCause(() => Effect14.void)));
6565
+ const perform = (effect) => Effect16.runSync((effect ?? Effect16.void).pipe(Effect16.catchAllCause(() => Effect16.void)));
6275
6566
  pi.registerProvider("magnitude", {
6276
6567
  api: "openai-completions",
6277
6568
  streamSimple: (model2, context, options) => {
6278
6569
  if (model2.api !== "openai-completions") {
6279
6570
  throw new Error(`Magnitude for Pi requires openai-completions, received ${model2.api}`);
6280
6571
  }
6281
- const response = tracker && Effect14.runSync(tracker.beginResponse(model2.name));
6572
+ const response = tracker && Effect16.runSync(tracker.beginResponse(model2.name));
6282
6573
  const stream = completions.streamSimple(model2, context, {
6283
6574
  ...options,
6284
- fetch: scope ? makeObservingFetch(options?.fetch ?? globalThis.fetch, () => response?.begin ?? Effect14.succeed({ observe: () => Effect14.void, finish: Effect14.void, fail: Effect14.void }), scope) : options?.fetch ?? globalThis.fetch
6575
+ fetch: scope ? makeObservingFetch(options?.fetch ?? globalThis.fetch, () => response?.begin ?? Effect16.succeed({ observe: () => Effect16.void, finish: Effect16.void, fail: Effect16.void }), scope) : options?.fetch ?? globalThis.fetch
6285
6576
  });
6286
6577
  if (response && scope)
6287
- Effect14.runFork(Effect14.forkIn(Effect14.tryPromise(() => stream.result()).pipe(Effect14.flatMap((message) => response.end(message.stopReason !== "error" && message.stopReason !== "aborted")), Effect14.catchAllCause(() => response.end(false))), scope));
6578
+ Effect16.runFork(Effect16.forkIn(Effect16.tryPromise(() => stream.result()).pipe(Effect16.flatMap((message) => response.end(message.stopReason !== "error" && message.stopReason !== "aborted")), Effect16.catchAllCause(() => response.end(false))), scope));
6288
6579
  return stream;
6289
6580
  }
6290
6581
  });
6291
6582
  pi.on("session_start", async (_event, ctx) => {
6292
6583
  if (scope)
6293
- await Effect14.runPromise(Scope6.close(scope, Exit4.void));
6294
- scope = Effect14.runSync(Scope6.make());
6295
- tracker = await Effect14.runPromise(makeProgressTracker(ctx.ui).pipe(Scope6.extend(scope)));
6584
+ await Effect16.runPromise(Scope7.close(scope, Exit5.void));
6585
+ scope = Effect16.runSync(Scope7.make());
6586
+ tracker = await Effect16.runPromise(makeProgressTracker(ctx.ui).pipe(Scope7.extend(scope)));
6296
6587
  });
6297
6588
  pi.on("model_select", (event) => {
6298
6589
  if (event.model.provider !== "magnitude")
@@ -6306,7 +6597,7 @@ function magnitudeExtension(pi) {
6306
6597
  pi.on("session_shutdown", async () => {
6307
6598
  await disposeOnboarding();
6308
6599
  if (scope)
6309
- await Effect14.runPromise(Scope6.close(scope, Exit4.void));
6600
+ await Effect16.runPromise(Scope7.close(scope, Exit5.void));
6310
6601
  tracker = undefined;
6311
6602
  scope = undefined;
6312
6603
  await disposeCommands();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magnitudedev/pi-extension",
3
- "version": "0.0.1-alpha.1",
3
+ "version": "0.0.1-alpha.2",
4
4
  "description": "Magnitude model controls and inference progress for Pi",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,6 +28,7 @@
28
28
  "@earendil-works/pi-tui": ">=0.83.0"
29
29
  },
30
30
  "devDependencies": {
31
+ "@magnitudedev/client-common": "workspace:*",
31
32
  "@effect/platform-bun": "^0.90.0",
32
33
  "@magnitudedev/release": "workspace:*",
33
34
  "@magnitudedev/utils": "workspace:*",