@magnitudedev/pi-extension 0.0.1 → 0.0.3-alpha.0
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 +40 -72
- package/dist/magnitude-plugin.json +4 -4
- package/dist/magnitude.js +48 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,95 +1,63 @@
|
|
|
1
1
|
# Magnitude for Pi
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
built-in working row above the editor.
|
|
3
|
+
Run Pi on local models. Free, private, and offline.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Magnitude runs the best local models for your hardware, plugged into the agent you already use.
|
|
6
|
+
It profiles your machine, recommends the models that fit, then downloads, tunes, and runs them.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
pi install npm:@magnitudedev/pi-extension
|
|
10
|
-
```
|
|
8
|
+
## Get started
|
|
11
9
|
|
|
12
|
-
|
|
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. The extension invokes `magnitude setup --host pi`; `--host` is hidden from help.
|
|
21
|
-
If an older CLI does not recognize that option, update it explicitly and retry; it is never silently
|
|
22
|
-
replaced.
|
|
23
|
-
|
|
24
|
-
No or Escape leaves “You can set up local models anytime with `/magnitude-setup`.” in the conversation.
|
|
25
|
-
The offer is remembered per Pi profile across restarts, reloads, and package updates. Existing
|
|
26
|
-
Magnitude model configurations, non-interactive modes, conversations, and startup prompts are left
|
|
27
|
-
alone. Run `/magnitude-setup` whenever you want to start onboarding yourself.
|
|
28
|
-
|
|
29
|
-
The package includes the Magnitude usage skill; an already-loaded skill of that name takes
|
|
30
|
-
precedence without a collision warning. `--no-skills` disables this fallback too. No separate CLI
|
|
31
|
-
installation is needed. npm must be available with a writable global prefix, as for a normal npm
|
|
32
|
-
CLI installation. Merely loading the extension does not install software.
|
|
33
|
-
|
|
34
|
-
If you already have Magnitude and a local model, connect directly:
|
|
10
|
+
Install the extension:
|
|
35
11
|
|
|
36
12
|
```sh
|
|
37
|
-
|
|
13
|
+
pi install npm:@magnitudedev/pi-extension
|
|
38
14
|
```
|
|
39
15
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
install the Magnitude CLI, or start its service; the connection command
|
|
43
|
-
does all connection configuration and can be run safely after a standalone package install.
|
|
16
|
+
Open Pi and accept the setup offer. Magnitude walks you through the best models for your machine,
|
|
17
|
+
downloads your selection, and connects it to Pi. You don't need Magnitude installed beforehand.
|
|
44
18
|
|
|
45
|
-
|
|
46
|
-
RPC endpoint at port 10100. When necessary the SDK runs `magnitude service start`; it does not use
|
|
47
|
-
CLI output as a model API. If `/stop-model` encounters a protocol mismatch, the
|
|
48
|
-
extension runs `magnitude connections sync pi` once to install the exact plugin version selected by
|
|
49
|
-
the installed CLI, then reloads Pi. Retry your model command after reload; it is never replayed
|
|
50
|
-
automatically. Failed sync reports the error without reloading or looping. Manually owned incompatible
|
|
51
|
-
packages are not replaced. Autocomplete and inference callbacks never trigger an update. During
|
|
52
|
-
requests to the `magnitude` provider, it opts into Magnitude progress events and uses Pi's working
|
|
53
|
-
row for model loading, prefill, and active-work timing. When Pi successfully completes a run, a one-line summary
|
|
54
|
-
immediately above the editor shows the model's display name, total Pi agent-run time, first-token
|
|
55
|
-
latency, and token-weighted generation throughput. Pi extensions execute with your user permissions.
|
|
19
|
+
You can also start setup anytime with `/magnitude-setup`.
|
|
56
20
|
|
|
57
|
-
|
|
21
|
+
Requires Pi 0.83.0 or newer. Magnitude supports macOS and Linux, and Windows through WSL.
|
|
22
|
+
An internet connection is needed for installation and model downloads; after that, you can work offline.
|
|
58
23
|
|
|
59
|
-
|
|
60
|
-
- `/stop-model` — stop the active model
|
|
24
|
+
## Why Magnitude?
|
|
61
25
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
26
|
+
- **Free to run:** no token costs, API keys, or rate limits
|
|
27
|
+
- **Private and offline:** local model requests stay on your machine
|
|
28
|
+
- **Recommends what fits:** the best models for your hardware, with estimated tok/s
|
|
29
|
+
- **Tuned end to end:** inference settings chosen for your machine
|
|
30
|
+
- **Models on demand:** loaded when Pi needs them, unloaded when idle or memory gets tight
|
|
31
|
+
- **Live performance stats:** see model loading, prompt processing, and time spent working
|
|
65
32
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
The SDK is a build-time workspace dependency, not a separately published or installed package.
|
|
33
|
+
After each completed run, a summary shows the model, time worked, time to first token, and tokens per
|
|
34
|
+
second. It stays in your chat history so you can refer back to it.
|
|
69
35
|
|
|
70
|
-
|
|
36
|
+
## Using your models
|
|
71
37
|
|
|
72
|
-
|
|
73
|
-
|
|
38
|
+
Choose an installed Magnitude model from Pi's `/model` selector. To discover or install more models,
|
|
39
|
+
ask your agent:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
Use Magnitude to recommend the best local models for my hardware and help me install one.
|
|
74
43
|
```
|
|
75
44
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
and keeps the current source CLI available until Pi exits. Exiting Pi stops the development runtime
|
|
81
|
-
and restores the service state that existed before launch. The launcher inherits the current
|
|
82
|
-
environment; it does not start or configure tracing.
|
|
45
|
+
Use `/magnitude-setup` to run guided setup again, or `/stop-model` to unload the active model and
|
|
46
|
+
free its memory.
|
|
47
|
+
|
|
48
|
+
### Already using Magnitude?
|
|
83
49
|
|
|
84
|
-
|
|
50
|
+
Connect your installed models to Pi:
|
|
85
51
|
|
|
86
52
|
```sh
|
|
87
|
-
|
|
53
|
+
magnitude connections add pi
|
|
88
54
|
```
|
|
89
55
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
56
|
+
Then restart Pi or run `/reload`.
|
|
57
|
+
|
|
58
|
+
## Learn more
|
|
59
|
+
|
|
60
|
+
- [Documentation](https://docs.magnitude.dev)
|
|
61
|
+
- [GitHub](https://github.com/magnitudedev/magnitude)
|
|
62
|
+
- [Discord](https://discord.gg/EHt48pPWdC)
|
|
63
|
+
- [Report an issue](https://github.com/magnitudedev/magnitude/issues)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magnitudedev/pi-extension",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3-alpha.0",
|
|
4
4
|
"rpcVersion": 1,
|
|
5
|
-
"contentFingerprint": "
|
|
5
|
+
"contentFingerprint": "8de1ffd943ecccad03f811d1b61bad853c2f0fb249308e8aecd00a8a504ed7fd",
|
|
6
6
|
"files": {
|
|
7
|
-
"README.md": "
|
|
8
|
-
"dist/magnitude.js": "
|
|
7
|
+
"README.md": "c6a121075d1ccacc4db063dd8ff1a336a04f77a7f444acba12e1628df32fa3f5",
|
|
8
|
+
"dist/magnitude.js": "e23b9692b7cd00bd01a68ba1bfd2c32a83c22017fa964008049b5de30c35a5cb",
|
|
9
9
|
"dist/skills/magnitude/SKILL.md": "37de67f0c7b831415f6298c8785b7ae97d5cfe454dc778651d96114840d2ace2"
|
|
10
10
|
}
|
|
11
11
|
}
|
package/dist/magnitude.js
CHANGED
|
@@ -5985,18 +5985,21 @@ var PiSetupLive = Layer6.effect(PiSetup, Effect12.gen(function* () {
|
|
|
5985
5985
|
const fs = yield* FileSystem.FileSystem;
|
|
5986
5986
|
const executor = yield* CommandExecutor3.CommandExecutor;
|
|
5987
5987
|
return {
|
|
5988
|
-
run: (ctx) => Effect12.scoped(Effect12.gen(function* () {
|
|
5988
|
+
run: (ctx, activateModel) => Effect12.scoped(Effect12.gen(function* () {
|
|
5989
5989
|
const executable = yield* withPiPreparation(ctx, (setMessage) => prepareMagnitudeCli(ctx.cwd, setMessage));
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5990
|
+
return yield* withPiTerminal(ctx, Effect12.gen(function* () {
|
|
5991
|
+
const termination = yield* runInteractiveProcess({
|
|
5992
|
+
executable,
|
|
5993
|
+
args: ["setup", "--host", "pi"],
|
|
5994
|
+
environment: process.env,
|
|
5995
|
+
workingDirectory: ctx.cwd
|
|
5996
|
+
});
|
|
5997
|
+
if (!(yield* validateSetupTermination(termination)))
|
|
5998
|
+
return { _tag: "Cancelled" };
|
|
5999
|
+
const modelId = yield* readSetupModel.pipe(Effect12.provide(MagnitudeClient.layer({ autoStart: false }).pipe(Layer6.provide(FetchHttpClient2.layer))));
|
|
6000
|
+
yield* activateModel(modelId);
|
|
6001
|
+
return { _tag: "Completed", modelId };
|
|
5995
6002
|
}));
|
|
5996
|
-
if (!(yield* validateSetupTermination(termination)))
|
|
5997
|
-
return { _tag: "Cancelled" };
|
|
5998
|
-
const modelId = yield* readSetupModel.pipe(Effect12.provide(MagnitudeClient.layer({ autoStart: false }).pipe(Layer6.provide(FetchHttpClient2.layer))));
|
|
5999
|
-
return { _tag: "Completed", modelId };
|
|
6000
6003
|
})).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)}`)))
|
|
6001
6004
|
};
|
|
6002
6005
|
}));
|
|
@@ -6010,19 +6013,16 @@ var registerMagnitudeSetup = (pi, layer4 = PiSetupLive.pipe(Layer6.provide(NodeC
|
|
|
6010
6013
|
if (!ctx.isIdle() || ctx.hasPendingMessages())
|
|
6011
6014
|
return yield* failure("Wait for the current task to finish, then run /magnitude-setup.");
|
|
6012
6015
|
const setup = yield* PiSetup;
|
|
6013
|
-
const result = yield* setup.run(ctx)
|
|
6014
|
-
if (result._tag !== "Completed")
|
|
6015
|
-
return false;
|
|
6016
|
-
yield* Effect12.tryPromise({
|
|
6016
|
+
const result = yield* setup.run(ctx, (modelId) => Effect12.tryPromise({
|
|
6017
6017
|
try: async () => {
|
|
6018
6018
|
await ctx.modelRegistry.refresh();
|
|
6019
|
-
const model2 = ctx.modelRegistry.find("magnitude",
|
|
6019
|
+
const model2 = ctx.modelRegistry.find("magnitude", modelId);
|
|
6020
6020
|
if (!model2 || !await pi.setModel(model2))
|
|
6021
6021
|
throw new Error("The selected model is not available in Pi");
|
|
6022
6022
|
},
|
|
6023
6023
|
catch: (error) => failure(`Magnitude setup completed, but Pi could not activate the model: ${String(error)}. Run /reload and select it with /model.`)
|
|
6024
|
-
});
|
|
6025
|
-
return
|
|
6024
|
+
}));
|
|
6025
|
+
return result._tag === "Completed";
|
|
6026
6026
|
});
|
|
6027
6027
|
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(() => {
|
|
6028
6028
|
ctx.ui.notify(error.message, "error");
|
|
@@ -6238,9 +6238,16 @@ var makeObservingFetch = (fetchImplementation, begin, scope) => {
|
|
|
6238
6238
|
};
|
|
6239
6239
|
|
|
6240
6240
|
// extensions/progress.ts
|
|
6241
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
6242
6241
|
import { Data as Data3, Effect as Effect15, Fiber as Fiber3, Option as Option17, Queue, Schema as Schema55 } from "effect";
|
|
6243
|
-
var
|
|
6242
|
+
var MAGNITUDE_SUMMARY_ENTRY_TYPE = "magnitude-inference-summary";
|
|
6243
|
+
var Milliseconds = Schema55.Number.pipe(Schema55.finite(), Schema55.nonNegative());
|
|
6244
|
+
var ProgressSummary = Schema55.Struct({
|
|
6245
|
+
modelName: Schema55.String,
|
|
6246
|
+
elapsedMs: Milliseconds,
|
|
6247
|
+
ttftMs: Milliseconds,
|
|
6248
|
+
generatedTokens: Schema55.Number.pipe(Schema55.int(), Schema55.nonNegative()),
|
|
6249
|
+
decodeMs: Milliseconds
|
|
6250
|
+
});
|
|
6244
6251
|
var RequestId = Schema55.Number.pipe(Schema55.int(), Schema55.brand("ProgressRequestId"));
|
|
6245
6252
|
|
|
6246
6253
|
class Observing extends Data3.TaggedClass("Observing") {
|
|
@@ -6276,27 +6283,28 @@ var runMachine = defineFSM({ Idle: Idle2, Working, Settled, Disposed }, {
|
|
|
6276
6283
|
});
|
|
6277
6284
|
var seconds = (ms) => `${(Math.max(0, ms) / 1000).toFixed(1)}s`;
|
|
6278
6285
|
var count = (n) => n < 1000 ? String(Math.round(n)) : `${(n / (n < 1e6 ? 1000 : 1e6)).toFixed(1).replace(/\.0$/, "")}${n < 1e6 ? "k" : "m"}`;
|
|
6279
|
-
var
|
|
6286
|
+
var formatElapsed = (ms) => {
|
|
6280
6287
|
const s = Math.floor(Math.max(0, ms) / 1000);
|
|
6281
|
-
return s
|
|
6288
|
+
return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${s % 60}s`;
|
|
6282
6289
|
};
|
|
6290
|
+
var formatSummary = (summary) => `● ${summary.modelName} worked for ${summary.elapsedMs < 1000 ? "<1s" : formatElapsed(summary.elapsedMs)}` + ` · ${seconds(summary.ttftMs)} TTFT` + (summary.decodeMs > 0 && summary.generatedTokens > 0 ? ` · ${(summary.generatedTokens * 1000 / summary.decodeMs).toFixed(1)} tok/s` : "");
|
|
6283
6291
|
var formatLiveProgress = ({ progress, modelName, startedAt }, now) => {
|
|
6284
6292
|
switch (progress.phase) {
|
|
6285
6293
|
case "queued":
|
|
6286
6294
|
case "preparing":
|
|
6287
6295
|
return;
|
|
6288
6296
|
case "model_loading":
|
|
6289
|
-
return `Loading ${modelName} into memory · ${Math.round(Math.max(0, Math.min(1, progress.fraction)) * 100)}% · ${
|
|
6297
|
+
return `Loading ${modelName} into memory · ${Math.round(Math.max(0, Math.min(1, progress.fraction)) * 100)}% · ${formatElapsed(now - startedAt)}`;
|
|
6290
6298
|
case "generating":
|
|
6291
|
-
return `Working · ${
|
|
6299
|
+
return `Working · ${formatElapsed(now - startedAt)}`;
|
|
6292
6300
|
case "prefill": {
|
|
6293
6301
|
const cached = Math.min(progress.cached_tokens, progress.total_tokens);
|
|
6294
6302
|
const completed = Math.min(Math.max(progress.completed_tokens, cached), progress.total_tokens);
|
|
6295
|
-
return `Prefilling prompt · ${count(completed - cached)} / ${count(progress.total_tokens - cached)} tokens · ${count(cached)} cached · ${
|
|
6303
|
+
return `Prefilling prompt · ${count(completed - cached)} / ${count(progress.total_tokens - cached)} tokens · ${count(cached)} cached · ${formatElapsed(now - startedAt)}`;
|
|
6296
6304
|
}
|
|
6297
6305
|
}
|
|
6298
6306
|
};
|
|
6299
|
-
var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(function* () {
|
|
6307
|
+
var makeProgressTracker = (ui, appendSummary, now = () => performance.now()) => Effect15.gen(function* () {
|
|
6300
6308
|
let state = new Idle2;
|
|
6301
6309
|
let nextId = 0;
|
|
6302
6310
|
let active;
|
|
@@ -6304,7 +6312,6 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6304
6312
|
let nextResponseId = 0;
|
|
6305
6313
|
const wake = yield* Queue.sliding(1);
|
|
6306
6314
|
const present = (f) => Effect15.sync(f).pipe(Effect15.catchAllCause(() => Effect15.void));
|
|
6307
|
-
const clearSummary = present(() => ui.setWidget(MAGNITUDE_SUMMARY_WIDGET_KEY, undefined));
|
|
6308
6315
|
const resetRow = present(() => ui.setWorkingMessage());
|
|
6309
6316
|
const render2 = present(() => {
|
|
6310
6317
|
if (active)
|
|
@@ -6320,14 +6327,17 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6320
6327
|
const settled = state;
|
|
6321
6328
|
state = runMachine.transition(settled, "Idle", {});
|
|
6322
6329
|
const timings = [...settled.run.completed.entries()].filter(([id]) => settled.run.accepted.has(id)).sort(([a], [b]) => a - b).map(([, value]) => value);
|
|
6323
|
-
if ([...settled.run.responses.values()].some((outcome) => !Option17.getOrElse(outcome, () => false)) || timings.length === 0)
|
|
6324
|
-
yield* clearSummary;
|
|
6330
|
+
if ([...settled.run.responses.values()].some((outcome) => !Option17.getOrElse(outcome, () => false)) || timings.length === 0)
|
|
6325
6331
|
return;
|
|
6326
|
-
}
|
|
6327
6332
|
const tokens = timings.reduce((sum, t) => sum + t.predicted_n, 0);
|
|
6328
6333
|
const decodeMs = timings.reduce((sum, t) => sum + t.predicted_ms, 0);
|
|
6329
|
-
|
|
6330
|
-
|
|
6334
|
+
yield* present(() => appendSummary(ProgressSummary.make({
|
|
6335
|
+
modelName: settled.run.modelName,
|
|
6336
|
+
elapsedMs: Math.max(0, settled.settledAt - settled.run.startedAt),
|
|
6337
|
+
ttftMs: timings[0].time_to_first_token_ms,
|
|
6338
|
+
generatedTokens: tokens,
|
|
6339
|
+
decodeMs
|
|
6340
|
+
})));
|
|
6331
6341
|
});
|
|
6332
6342
|
const clear = Effect15.gen(function* () {
|
|
6333
6343
|
if (state._tag === "Disposed")
|
|
@@ -6337,7 +6347,6 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6337
6347
|
active = undefined;
|
|
6338
6348
|
latest = undefined;
|
|
6339
6349
|
yield* resetRow;
|
|
6340
|
-
yield* clearSummary;
|
|
6341
6350
|
});
|
|
6342
6351
|
const startRun = (modelName) => Effect15.gen(function* () {
|
|
6343
6352
|
if (state._tag === "Disposed")
|
|
@@ -6347,7 +6356,6 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6347
6356
|
if (state._tag !== "Idle")
|
|
6348
6357
|
return;
|
|
6349
6358
|
state = runMachine.transition(state, "Working", { run: { startedAt: now(), modelName, requests: new Map, completed: new Map, responses: new Map, accepted: new Set } });
|
|
6350
|
-
yield* clearSummary;
|
|
6351
6359
|
});
|
|
6352
6360
|
const timer = yield* Effect15.forever(Effect15.gen(function* () {
|
|
6353
6361
|
yield* Queue.take(wake);
|
|
@@ -6395,7 +6403,6 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6395
6403
|
if (!successful && latest !== undefined && requests.includes(latest)) {
|
|
6396
6404
|
active = undefined;
|
|
6397
6405
|
yield* resetRow;
|
|
6398
|
-
yield* clearSummary;
|
|
6399
6406
|
}
|
|
6400
6407
|
yield* finalize;
|
|
6401
6408
|
});
|
|
@@ -6459,8 +6466,13 @@ var makeProgressTracker = (ui, now = () => performance.now()) => Effect15.gen(fu
|
|
|
6459
6466
|
});
|
|
6460
6467
|
|
|
6461
6468
|
// extensions/magnitude.ts
|
|
6462
|
-
import {
|
|
6469
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
6470
|
+
import { Effect as Effect16, Exit as Exit5, Option as Option18, Schema as Schema56, Scope as Scope7 } from "effect";
|
|
6463
6471
|
function magnitudeExtension(pi) {
|
|
6472
|
+
pi.registerEntryRenderer(MAGNITUDE_SUMMARY_ENTRY_TYPE, (entry, _options, theme) => {
|
|
6473
|
+
const summary = Schema56.decodeUnknownOption(ProgressSummary)(entry.data);
|
|
6474
|
+
return Option18.isSome(summary) ? new Text(theme.fg("muted", formatSummary(summary.value)), 0, 0) : undefined;
|
|
6475
|
+
});
|
|
6464
6476
|
const completions = openAICompletionsApi();
|
|
6465
6477
|
let tracker;
|
|
6466
6478
|
let scope;
|
|
@@ -6487,7 +6499,7 @@ function magnitudeExtension(pi) {
|
|
|
6487
6499
|
if (scope)
|
|
6488
6500
|
await Effect16.runPromise(Scope7.close(scope, Exit5.void));
|
|
6489
6501
|
scope = Effect16.runSync(Scope7.make());
|
|
6490
|
-
tracker = await Effect16.runPromise(makeProgressTracker(ctx.ui).pipe(Scope7.extend(scope)));
|
|
6502
|
+
tracker = await Effect16.runPromise(makeProgressTracker(ctx.ui, (summary) => pi.appendEntry(MAGNITUDE_SUMMARY_ENTRY_TYPE, summary)).pipe(Scope7.extend(scope)));
|
|
6491
6503
|
});
|
|
6492
6504
|
pi.on("model_select", (event) => {
|
|
6493
6505
|
if (event.model.provider !== "magnitude")
|