@caupulican/pi-adaptative 0.80.94 → 0.80.96

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +39 -0
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/models/fitness-store.d.ts +2 -0
  6. package/dist/core/models/fitness-store.d.ts.map +1 -1
  7. package/dist/core/models/fitness-store.js +10 -0
  8. package/dist/core/models/fitness-store.js.map +1 -1
  9. package/dist/core/models/local-registration.d.ts +18 -0
  10. package/dist/core/models/local-registration.d.ts.map +1 -0
  11. package/dist/core/models/local-registration.js +83 -0
  12. package/dist/core/models/local-registration.js.map +1 -0
  13. package/dist/core/models/local-runtime.d.ts +84 -0
  14. package/dist/core/models/local-runtime.d.ts.map +1 -0
  15. package/dist/core/models/local-runtime.js +219 -0
  16. package/dist/core/models/local-runtime.js.map +1 -0
  17. package/dist/core/models/model-ref.d.ts +19 -0
  18. package/dist/core/models/model-ref.d.ts.map +1 -0
  19. package/dist/core/models/model-ref.js +61 -0
  20. package/dist/core/models/model-ref.js.map +1 -0
  21. package/dist/core/slash-commands.d.ts.map +1 -1
  22. package/dist/core/slash-commands.js +4 -0
  23. package/dist/core/slash-commands.js.map +1 -1
  24. package/dist/core/toolkit/reflex-interpreter.d.ts +28 -0
  25. package/dist/core/toolkit/reflex-interpreter.d.ts.map +1 -0
  26. package/dist/core/toolkit/reflex-interpreter.js +62 -0
  27. package/dist/core/toolkit/reflex-interpreter.js.map +1 -0
  28. package/dist/core/tools/run-toolkit-script.d.ts +8 -0
  29. package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
  30. package/dist/core/tools/run-toolkit-script.js +21 -3
  31. package/dist/core/tools/run-toolkit-script.js.map +1 -1
  32. package/dist/modes/interactive/interactive-mode.d.ts +7 -0
  33. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  34. package/dist/modes/interactive/interactive-mode.js +175 -0
  35. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  36. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  37. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  38. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  39. package/examples/extensions/sandbox/package-lock.json +2 -2
  40. package/examples/extensions/sandbox/package.json +1 -1
  41. package/examples/extensions/with-deps/package-lock.json +2 -2
  42. package/examples/extensions/with-deps/package.json +1 -1
  43. package/npm-shrinkwrap.json +12 -12
  44. package/package.json +4 -4
@@ -22,6 +22,10 @@ import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/htt
22
22
  import { KeybindingsManager } from "../../core/keybindings.js";
23
23
  import { createCompactionSummaryMessage } from "../../core/messages.js";
24
24
  import { cliProviderAliases, defaultModelPerProvider, findExactModelReferenceMatch, resolveCliModel, resolveModelScope, } from "../../core/model-resolver.js";
25
+ import { FitnessStore } from "../../core/models/fitness-store.js";
26
+ import { registerLocalModel, unregisterLocalModel } from "../../core/models/local-registration.js";
27
+ import { OllamaRuntime } from "../../core/models/local-runtime.js";
28
+ import { normalizeModelSource } from "../../core/models/model-ref.js";
25
29
  import { DefaultPackageManager } from "../../core/package-manager.js";
26
30
  import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
27
31
  import { getPendingReloadBlockers } from "../../core/reload-blockers.js";
@@ -2478,6 +2482,11 @@ export class InteractiveMode {
2478
2482
  }
2479
2483
  return;
2480
2484
  }
2485
+ if (text === "/models" || text.startsWith("/models ")) {
2486
+ void this.handleModelsCommand(text.slice("/models".length).trim());
2487
+ this.editor.setText("");
2488
+ return;
2489
+ }
2481
2490
  if (text === "/context") {
2482
2491
  this.showStatus(this.session.formatContextCompositionDashboard());
2483
2492
  this.editor.setText("");
@@ -5129,6 +5138,172 @@ export class InteractiveMode {
5129
5138
  this.settingsManager.setAutoLearnSettings(preset, scope);
5130
5139
  this.updateAutoLearnFooter();
5131
5140
  }
5141
+ _localRuntime;
5142
+ get localRuntime() {
5143
+ this._localRuntime ??= new OllamaRuntime({ agentDir: getAgentDir() });
5144
+ return this._localRuntime;
5145
+ }
5146
+ /**
5147
+ * /models — USER-invoked local model lifecycle (never a model-invokable tool):
5148
+ * list/add/remove/stop per local-model-lifecycle-design.md. Removal is explicit-only with
5149
+ * full disclosure; a pasted install command is parsed for its ref, never executed.
5150
+ */
5151
+ async handleModelsCommand(argsText) {
5152
+ const [action = "list", ...rest] = argsText.split(/\s+/).filter(Boolean);
5153
+ try {
5154
+ if (action === "stop") {
5155
+ const stopped = this.localRuntime.stop();
5156
+ this.showStatus(stopped.stopped
5157
+ ? "Pi-managed local model server stopped (models remain installed)."
5158
+ : "No pi-managed server running (a system server, if any, is not pi's to stop).");
5159
+ return;
5160
+ }
5161
+ if (action === "add") {
5162
+ const rawRef = rest.join(" ");
5163
+ if (!rawRef) {
5164
+ this.showStatus("Usage: /models add <ollama-tag | hf.co/org/repo[:quant] | huggingface URL | pasted install command>");
5165
+ return;
5166
+ }
5167
+ const source = normalizeModelSource(rawRef);
5168
+ if (source.type === "rejected") {
5169
+ this.showStatus(`Not added: ${source.reason}`);
5170
+ return;
5171
+ }
5172
+ if (source.type === "api") {
5173
+ this.showStatus(`${source.ref} is an API model — nothing to install. Configure auth for the provider, then probe it with /fitness ${source.ref}.`);
5174
+ return;
5175
+ }
5176
+ await this.addLocalModel(source.pullRef);
5177
+ return;
5178
+ }
5179
+ if (action === "remove") {
5180
+ const ref = rest[0];
5181
+ const confirmed = rest[1] === "confirm";
5182
+ if (!ref) {
5183
+ this.showStatus("Usage: /models remove <ref> confirm");
5184
+ return;
5185
+ }
5186
+ await this.removeLocalModel(ref, confirmed);
5187
+ return;
5188
+ }
5189
+ await this.listLocalModels();
5190
+ }
5191
+ catch (error) {
5192
+ this.showError(error instanceof Error ? error.message : String(error));
5193
+ }
5194
+ }
5195
+ async ensureLocalServer() {
5196
+ const status = await this.localRuntime.detect();
5197
+ if (status.serverUp)
5198
+ return true;
5199
+ if (!status.binaryPath) {
5200
+ for (const line of this.localRuntime.installGuide())
5201
+ this.showStatus(line);
5202
+ return false;
5203
+ }
5204
+ this.showStatus(`Starting local model server (${status.binarySource} binary, owned storage: ${status.ownedModelsDir})…`);
5205
+ const started = await this.localRuntime.start();
5206
+ if (!started.started) {
5207
+ this.showStatus(`Could not start the local server: ${started.reason}`);
5208
+ return false;
5209
+ }
5210
+ return true;
5211
+ }
5212
+ async listLocalModels() {
5213
+ const status = await this.localRuntime.detect();
5214
+ if (!status.serverUp) {
5215
+ if (!status.binaryPath) {
5216
+ for (const line of this.localRuntime.installGuide())
5217
+ this.showStatus(line);
5218
+ return;
5219
+ }
5220
+ this.showStatus(`Local server not running (binary: ${status.binarySource}). /models add starts it on demand; /fitness probes registered models.`);
5221
+ return;
5222
+ }
5223
+ const models = await this.localRuntime.list();
5224
+ const fitness = FitnessStore.forAgentDir(getAgentDir()).getForHost();
5225
+ const lines = [
5226
+ `Local models (${status.managedByPi ? `pi-managed server, storage: ${status.ownedModelsDir}` : "system server — storage owned by the system daemon"}):`,
5227
+ ...(models.length === 0 ? [" (none installed — /models add <ref>)"] : []),
5228
+ ...models.map((model) => {
5229
+ const report = fitness.find((entry) => entry.model === `ollama/${model.name}`);
5230
+ const gb = (model.sizeBytes / 1e9).toFixed(2);
5231
+ const probe = report
5232
+ ? `probed ${report.at.slice(0, 10)}: digest ${report.report.digest?.succeeded ?? "?"}/${report.report.digest?.total ?? "?"}, tool-calls ${report.report.toolCall.succeeded}/${report.report.toolCall.total}${report.report.tokensPerSecond ? `, ~${report.report.tokensPerSecond} tok/s` : ""}`
5233
+ : `unprobed — run /fitness ollama/${model.name}`;
5234
+ return ` - ${model.name} (${gb} GB) · ${probe}`;
5235
+ }),
5236
+ "Commands: /models add <ref> · /models remove <ref> confirm · /models stop",
5237
+ ];
5238
+ for (const line of lines)
5239
+ this.showStatus(line);
5240
+ }
5241
+ async addLocalModel(pullRef) {
5242
+ if (!(await this.ensureLocalServer()))
5243
+ return;
5244
+ this.showStatus(`Pulling ${pullRef}… (weights land in the server's model storage)`);
5245
+ let lastShown = 0;
5246
+ const pulled = await this.localRuntime.pull(pullRef, (progress) => {
5247
+ const now = Date.now();
5248
+ if (now - lastShown > 2000) {
5249
+ lastShown = now;
5250
+ this.showStatus(` ${pullRef}: ${progress}`);
5251
+ }
5252
+ });
5253
+ if (!pulled.ok) {
5254
+ this.showStatus(`Pull failed: ${pulled.error}`);
5255
+ return;
5256
+ }
5257
+ const registration = registerLocalModel({
5258
+ agentDir: getAgentDir(),
5259
+ ref: pullRef,
5260
+ baseUrl: this.localRuntime.baseUrl,
5261
+ });
5262
+ if (!registration.ok) {
5263
+ this.showStatus(`Pulled, but not auto-registered: ${registration.reason}`);
5264
+ if (registration.manualSnippet) {
5265
+ this.showStatus(`Add this to ${registration.modelsJsonPath} yourself:\n${registration.manualSnippet}`);
5266
+ }
5267
+ return;
5268
+ }
5269
+ this.session.modelRegistry.refresh();
5270
+ this.showStatus(`${pullRef} installed and registered as ollama/${pullRef}. Probing fitness…`);
5271
+ await this.runFitnessAndAssign(`ollama/${pullRef}`);
5272
+ }
5273
+ async removeLocalModel(ref, confirmed) {
5274
+ const status = await this.localRuntime.detect();
5275
+ if (!status.serverUp) {
5276
+ this.showStatus("Local server not running — start it (any /models action) before removing.");
5277
+ return;
5278
+ }
5279
+ const models = await this.localRuntime.list();
5280
+ const target = models.find((model) => model.name === ref);
5281
+ if (!target) {
5282
+ this.showStatus(`${ref} is not installed. Installed: ${models.map((model) => model.name).join(", ") || "(none)"}`);
5283
+ return;
5284
+ }
5285
+ if (!confirmed) {
5286
+ // EXPLICIT USER ACTION ONLY: full disclosure, then require the confirm token.
5287
+ const gb = (target.sizeBytes / 1e9).toFixed(2);
5288
+ this.showStatus([
5289
+ `Removing ${ref} will delete:`,
5290
+ ` - model weights (${gb} GB) from ${status.managedByPi ? status.ownedModelsDir : "the system server's storage"}`,
5291
+ ` - the ollama/${ref} entry in models.json`,
5292
+ ` - its cached fitness report for this host`,
5293
+ `Run: /models remove ${ref} confirm`,
5294
+ ].join("\n"));
5295
+ return;
5296
+ }
5297
+ const removed = await this.localRuntime.remove(ref);
5298
+ if (!removed.ok) {
5299
+ this.showStatus(`Remove failed: ${removed.error}`);
5300
+ return;
5301
+ }
5302
+ unregisterLocalModel({ agentDir: getAgentDir(), ref });
5303
+ FitnessStore.forAgentDir(getAgentDir()).remove(`ollama/${ref}`);
5304
+ this.session.modelRegistry.refresh();
5305
+ this.showStatus(`${ref} removed: weights deleted, registration and fitness report dropped.`);
5306
+ }
5132
5307
  /** /fitness with no args: pick a model from the configured registry, probe it, assign a role. */
5133
5308
  showFitnessModelSelector() {
5134
5309
  this.showSelector((done) => {