@caupulican/pi-adaptative 0.80.48 → 0.80.50

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 (31) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/core/model-resolver.d.ts +13 -0
  3. package/dist/core/model-resolver.d.ts.map +1 -1
  4. package/dist/core/model-resolver.js +44 -0
  5. package/dist/core/model-resolver.js.map +1 -1
  6. package/dist/core/sdk.d.ts.map +1 -1
  7. package/dist/core/sdk.js +20 -2
  8. package/dist/core/sdk.js.map +1 -1
  9. package/dist/main.d.ts.map +1 -1
  10. package/dist/main.js +28 -3
  11. package/dist/main.js.map +1 -1
  12. package/dist/modes/interactive/components/profile-resource-editor.d.ts +3 -0
  13. package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
  14. package/dist/modes/interactive/components/profile-resource-editor.js +78 -1
  15. package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
  16. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  17. package/dist/modes/interactive/components/settings-selector.js +4 -4
  18. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  19. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  20. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  21. package/dist/modes/interactive/interactive-mode.js +111 -25
  22. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  23. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  24. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  25. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  26. package/examples/extensions/sandbox/package-lock.json +2 -2
  27. package/examples/extensions/sandbox/package.json +1 -1
  28. package/examples/extensions/with-deps/package-lock.json +2 -2
  29. package/examples/extensions/with-deps/package.json +1 -1
  30. package/npm-shrinkwrap.json +12 -12
  31. package/package.json +4 -4
@@ -59,7 +59,7 @@ import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./c
59
59
  import { LoginDialogComponent } from "./components/login-dialog.js";
60
60
  import { ModelSelectorComponent } from "./components/model-selector.js";
61
61
  import { OAuthSelectorComponent } from "./components/oauth-selector.js";
62
- import { ProfileResourceEditorComponent, } from "./components/profile-resource-editor.js";
62
+ import { ProfileResourceEditorComponent, resolveResourceEditPath, } from "./components/profile-resource-editor.js";
63
63
  import { ProfileSelectorComponent } from "./components/profile-selector.js";
64
64
  import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
65
65
  import { SessionSelectorComponent } from "./components/session-selector.js";
@@ -3718,6 +3718,50 @@ export class InteractiveMode {
3718
3718
  this.ui.requestRender(true);
3719
3719
  }
3720
3720
  }
3721
+ async openEditorForPath(filePath) {
3722
+ let editorCmd = process.env.EDITOR || process.env.VISUAL;
3723
+ let isFallback = false;
3724
+ if (!editorCmd) {
3725
+ editorCmd = "vi";
3726
+ isFallback = true;
3727
+ }
3728
+ try {
3729
+ // Stop TUI to release terminal
3730
+ this.ui.stop();
3731
+ // Split by space to support editor arguments (e.g., "code --wait")
3732
+ const [editor, ...editorArgs] = editorCmd.split(" ");
3733
+ process.stdout.write(`Launching external editor: ${editorCmd} ${filePath}\nPi will resume when the editor exits.\n`);
3734
+ const status = await new Promise((resolve) => {
3735
+ const child = spawn(editor, [...editorArgs, filePath], {
3736
+ stdio: "inherit",
3737
+ shell: process.platform === "win32",
3738
+ });
3739
+ child.on("error", () => resolve(null));
3740
+ child.on("close", (code) => resolve(code));
3741
+ });
3742
+ if (status === null) {
3743
+ if (isFallback) {
3744
+ process.stdout.write(`\nError: Failed to launch fallback editor "vi".\n`);
3745
+ }
3746
+ else {
3747
+ process.stdout.write(`\nError: Failed to launch editor "${editorCmd}".\n`);
3748
+ }
3749
+ process.stdout.write(`Please set the $EDITOR or $VISUAL environment variable to edit inline.\n`);
3750
+ process.stdout.write(`Absolute file path: ${filePath}\n\nPress Enter to return to Pi...`);
3751
+ // Wait for enter key
3752
+ await new Promise((resolve) => {
3753
+ process.stdin.once("data", () => resolve());
3754
+ });
3755
+ }
3756
+ return status === 0;
3757
+ }
3758
+ finally {
3759
+ // Restart TUI
3760
+ this.ui.start();
3761
+ // Force full re-render since external editor uses alternate screen
3762
+ this.ui.requestRender(true);
3763
+ }
3764
+ }
3721
3765
  // =========================================================================
3722
3766
  // UI helpers
3723
3767
  // =========================================================================
@@ -5127,7 +5171,7 @@ export class InteractiveMode {
5127
5171
  const profiles = registry.listProfiles();
5128
5172
  const activeNames = this.settingsManager.getActiveResourceProfileNames();
5129
5173
  const options = [
5130
- { value: "(none)", label: "(none)", description: "No active profile (all resources enabled)" },
5174
+ { value: "(none)", label: "(none)", description: "No active profile/situation (all resources enabled)" },
5131
5175
  ...profiles.map((p) => ({
5132
5176
  value: p.name,
5133
5177
  label: p.name,
@@ -5135,7 +5179,7 @@ export class InteractiveMode {
5135
5179
  })),
5136
5180
  ];
5137
5181
  this.showSelector((done) => {
5138
- const selector = new SelectSubmenu("Profile / Situation", "Select the active runtime profile for this session. This is session-only unless saved elsewhere.", options, activeNames[0] || "(none)", (value) => {
5182
+ const selector = new SelectSubmenu("Profile / Situation", "Select the active runtime profile/situation for this session. This is session-only unless saved elsewhere.", options, activeNames[0] || "(none)", (value) => {
5139
5183
  done();
5140
5184
  void this.applyProfile(value === "(none)" ? "" : value).then(() => {
5141
5185
  void this.showSettingsSelector();
@@ -5156,24 +5200,28 @@ export class InteractiveMode {
5156
5200
  description: p.description || p.source,
5157
5201
  }));
5158
5202
  const options = [
5159
- { value: "create", label: "+ Create profile...", description: "Create a new resource profile definition." },
5203
+ {
5204
+ value: "create",
5205
+ label: "+ Create profile / situation...",
5206
+ description: "Create a new resource profile/situation definition.",
5207
+ },
5160
5208
  ];
5161
5209
  if (this.settingsManager.getActiveResourceProfileNames().length > 0) {
5162
5210
  options.push({
5163
5211
  value: "persist",
5164
- label: "Persist active profile to...",
5165
- description: "Save the current active-profile selection so it survives restart.",
5212
+ label: "Persist active profile / situation to...",
5213
+ description: "Save the current active profile/situation selection so it survives restart.",
5166
5214
  });
5167
5215
  }
5168
5216
  if (editableProfiles.length > 0) {
5169
5217
  options.push({
5170
5218
  value: "delete",
5171
- label: "Delete profile...",
5172
- description: "Remove a profile definition from where it is stored.",
5219
+ label: "Delete profile / situation...",
5220
+ description: "Remove a profile/situation definition from where it is stored.",
5173
5221
  });
5174
5222
  }
5175
5223
  this.showSelector((done) => {
5176
- const selector = new SelectSubmenu("Manage Profiles", "Create, delete, or persist profile definitions.", options, "", (value) => {
5224
+ const selector = new SelectSubmenu("Manage Profiles / Situations", "Create, delete, or persist profile/situation definitions.", options, "", (value) => {
5177
5225
  done();
5178
5226
  if (value === "create") {
5179
5227
  void this.createProfileFlow().then(() => {
@@ -5205,7 +5253,7 @@ export class InteractiveMode {
5205
5253
  { value: "global", label: "global", description: "~/.pi/agent/settings.json" },
5206
5254
  ];
5207
5255
  this.showSelector((done) => {
5208
- const selector = new SelectSubmenu("Persist Active Profile", "Choose where to write the active-profile selection.", scopeOptions, "directory", (value) => {
5256
+ const selector = new SelectSubmenu("Persist Active Profile / Situation", "Choose where to write the active profile/situation selection.", scopeOptions, "directory", (value) => {
5209
5257
  done();
5210
5258
  this.persistActiveProfile(value);
5211
5259
  void this.showSettingsSelector();
@@ -5224,7 +5272,7 @@ export class InteractiveMode {
5224
5272
  description: p.description || p.source,
5225
5273
  }));
5226
5274
  this.showSelector((done) => {
5227
- const selector = new SelectSubmenu("Delete Profile", "Pick a profile to delete.", editableProfiles, "", (value) => {
5275
+ const selector = new SelectSubmenu("Delete Profile / Situation", "Pick a profile/situation to delete.", editableProfiles, "", (value) => {
5228
5276
  done();
5229
5277
  this.deleteProfileFromSource(value);
5230
5278
  void this.showSettingsSelector();
@@ -5279,13 +5327,17 @@ export class InteractiveMode {
5279
5327
  const activeName = activeNames[0];
5280
5328
  if (!activeName || activeName === "(none)") {
5281
5329
  this.showSelector((done) => {
5282
- const selector = new SelectSubmenu("No Active Profile", "Select or create a profile to manage the library.", [
5330
+ const selector = new SelectSubmenu("No Active Profile / Situation", "Select or create a profile/situation to manage the library.", [
5283
5331
  {
5284
5332
  value: "select",
5285
- label: "Select existing profile...",
5286
- description: "Choose an existing profile to activate.",
5333
+ label: "Select existing profile / situation...",
5334
+ description: "Choose an existing profile/situation to activate.",
5335
+ },
5336
+ {
5337
+ value: "create",
5338
+ label: "Create new profile / situation...",
5339
+ description: "Create a new profile/situation definition.",
5287
5340
  },
5288
- { value: "create", label: "Create new profile...", description: "Create a new profile definition." },
5289
5341
  ], "select", (value) => {
5290
5342
  done();
5291
5343
  if (value === "create") {
@@ -5305,7 +5357,7 @@ export class InteractiveMode {
5305
5357
  const registry = this.settingsManager.getProfileRegistry();
5306
5358
  const profile = registry.getProfile(activeName);
5307
5359
  if (!profile) {
5308
- this.showError(`Active profile "${activeName}" not found in registry.`);
5360
+ this.showError(`Active profile/situation "${activeName}" not found in registry.`);
5309
5361
  return;
5310
5362
  }
5311
5363
  const scope = this.scopeForProfileSource(profile.source);
@@ -5314,7 +5366,7 @@ export class InteractiveMode {
5314
5366
  async createProfileAndOpenLibraryFlow() {
5315
5367
  const name = await new Promise((resolve) => {
5316
5368
  this.showSelector((done) => {
5317
- const input = new ExtensionInputComponent("Create Profile", "Enter profile name", (value) => {
5369
+ const input = new ExtensionInputComponent("Create Profile / Situation", "Enter profile/situation name", (value) => {
5318
5370
  done();
5319
5371
  resolve(value);
5320
5372
  }, () => {
@@ -5330,7 +5382,7 @@ export class InteractiveMode {
5330
5382
  }
5331
5383
  const trimmed = name.trim();
5332
5384
  if (!trimmed) {
5333
- this.showWarning("Profile name cannot be empty.");
5385
+ this.showWarning("Profile/situation name cannot be empty.");
5334
5386
  void this.openLibraryManagerFlow();
5335
5387
  return;
5336
5388
  }
@@ -5356,12 +5408,12 @@ export class InteractiveMode {
5356
5408
  description: p.description || p.source,
5357
5409
  }));
5358
5410
  if (editableProfiles.length === 0) {
5359
- this.showWarning("No existing profiles to select. Please create one.");
5411
+ this.showWarning("No existing profiles/situations to select. Please create one.");
5360
5412
  void this.createProfileAndOpenLibraryFlow();
5361
5413
  return;
5362
5414
  }
5363
5415
  this.showSelector((done) => {
5364
- const selector = new SelectSubmenu("Select Profile", "Pick a profile to activate and edit.", editableProfiles, "", (value) => {
5416
+ const selector = new SelectSubmenu("Select Profile / Situation", "Pick a profile/situation to activate and edit.", editableProfiles, "", (value) => {
5365
5417
  done();
5366
5418
  void this.applyProfile(value).then(() => {
5367
5419
  const profile = registry.getProfile(value);
@@ -5521,6 +5573,23 @@ export class InteractiveMode {
5521
5573
  done();
5522
5574
  void this.promptScopeChangeForProfile(profileName, currentScope);
5523
5575
  },
5576
+ onEdit: async (id, pathValue, kind) => {
5577
+ done();
5578
+ const resolvedEditPath = resolveResourceEditPath(id, pathValue, kind);
5579
+ if (!resolvedEditPath) {
5580
+ this.showWarning(`Resource "${id}" of kind "${kind}" has no editable file path.`);
5581
+ void this.openLibraryEditorForProfile(profileName, currentScope);
5582
+ return;
5583
+ }
5584
+ if (!fs.existsSync(resolvedEditPath)) {
5585
+ this.showError(`Resolved path for "${id}" does not exist: ${resolvedEditPath}`);
5586
+ void this.openLibraryEditorForProfile(profileName, currentScope);
5587
+ return;
5588
+ }
5589
+ await this.openEditorForPath(resolvedEditPath);
5590
+ await this.handleReloadCommand();
5591
+ void this.openLibraryEditorForProfile(profileName, currentScope);
5592
+ },
5524
5593
  });
5525
5594
  return { component: editor, focus: editor };
5526
5595
  });
@@ -5537,7 +5606,7 @@ export class InteractiveMode {
5537
5606
  { value: "global", label: "global", description: "~/.pi/agent/settings.json" },
5538
5607
  ];
5539
5608
  this.showSelector((done) => {
5540
- const selector = new SelectSubmenu("Change Profile Scope", `Select new scope for profile "${profileName}".`, scopeOptions, currentScope, (value) => {
5609
+ const selector = new SelectSubmenu("Change Profile / Situation Scope", `Select new scope for profile/situation "${profileName}".`, scopeOptions, currentScope, (value) => {
5541
5610
  done();
5542
5611
  void this.openLibraryEditorForProfile(profileName, value);
5543
5612
  }, () => {
@@ -5665,7 +5734,7 @@ export class InteractiveMode {
5665
5734
  async createProfileFlow() {
5666
5735
  const name = await new Promise((resolve) => {
5667
5736
  this.showSelector((done) => {
5668
- const input = new ExtensionInputComponent("Create Profile", "Enter profile name", (value) => {
5737
+ const input = new ExtensionInputComponent("Create Profile / Situation", "Enter profile/situation name", (value) => {
5669
5738
  done();
5670
5739
  resolve(value);
5671
5740
  }, () => {
@@ -5681,19 +5750,19 @@ export class InteractiveMode {
5681
5750
  }
5682
5751
  const trimmed = name.trim();
5683
5752
  if (!trimmed) {
5684
- this.showError("Profile name cannot be empty");
5753
+ this.showError("Profile/situation name cannot be empty");
5685
5754
  return this.createProfileFlow();
5686
5755
  }
5687
5756
  // Validate name rules using validateSkillName
5688
5757
  const errors = validateSkillName(trimmed);
5689
5758
  if (errors.length > 0) {
5690
- this.showError(`Invalid profile name: ${errors.join(", ")}`);
5759
+ this.showError(`Invalid profile/situation name: ${errors.join(", ")}`);
5691
5760
  return this.createProfileFlow();
5692
5761
  }
5693
5762
  // Collision check
5694
5763
  const existing = this.settingsManager.getProfileRegistry().getProfile(trimmed);
5695
5764
  if (existing) {
5696
- this.showError(`Profile "${trimmed}" already exists`);
5765
+ this.showError(`Profile/situation "${trimmed}" already exists`);
5697
5766
  return this.createProfileFlow();
5698
5767
  }
5699
5768
  // Open the resource editor on the NEW profile
@@ -5729,6 +5798,23 @@ export class InteractiveMode {
5729
5798
  done();
5730
5799
  this.ui.requestRender();
5731
5800
  },
5801
+ onEdit: async (id, pathValue, kind) => {
5802
+ done();
5803
+ const resolvedEditPath = resolveResourceEditPath(id, pathValue, kind);
5804
+ if (!resolvedEditPath) {
5805
+ this.showWarning(`Resource "${id}" of kind "${kind}" has no editable file path.`);
5806
+ void this.openNewProfileEditor(profileName);
5807
+ return;
5808
+ }
5809
+ if (!fs.existsSync(resolvedEditPath)) {
5810
+ this.showError(`Resolved path for "${id}" does not exist: ${resolvedEditPath}`);
5811
+ void this.openNewProfileEditor(profileName);
5812
+ return;
5813
+ }
5814
+ await this.openEditorForPath(resolvedEditPath);
5815
+ await this.handleReloadCommand();
5816
+ void this.openNewProfileEditor(profileName);
5817
+ },
5732
5818
  });
5733
5819
  return { component: editor, focus: editor };
5734
5820
  });