@caupulican/pi-adaptative 0.80.46 → 0.80.47

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 (32) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +1 -0
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/extensions/loader.d.ts.map +1 -1
  6. package/dist/core/extensions/loader.js +5 -0
  7. package/dist/core/extensions/loader.js.map +1 -1
  8. package/dist/core/extensions/runner.d.ts.map +1 -1
  9. package/dist/core/extensions/runner.js +1 -0
  10. package/dist/core/extensions/runner.js.map +1 -1
  11. package/dist/core/extensions/types.d.ts +3 -0
  12. package/dist/core/extensions/types.d.ts.map +1 -1
  13. package/dist/core/extensions/types.js.map +1 -1
  14. package/dist/core/settings-manager.d.ts +1 -1
  15. package/dist/core/settings-manager.d.ts.map +1 -1
  16. package/dist/core/settings-manager.js.map +1 -1
  17. package/dist/core/slash-commands.d.ts.map +1 -1
  18. package/dist/core/slash-commands.js +12 -0
  19. package/dist/core/slash-commands.js.map +1 -1
  20. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  21. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  22. package/dist/modes/interactive/interactive-mode.js +240 -0
  23. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  24. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  25. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  26. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  27. package/examples/extensions/sandbox/package-lock.json +2 -2
  28. package/examples/extensions/sandbox/package.json +1 -1
  29. package/examples/extensions/with-deps/package-lock.json +2 -2
  30. package/examples/extensions/with-deps/package.json +1 -1
  31. package/npm-shrinkwrap.json +12 -12
  32. package/package.json +4 -4
@@ -2541,6 +2541,24 @@ export class InteractiveMode {
2541
2541
  await this.handleReloadCommand();
2542
2542
  return;
2543
2543
  }
2544
+ if (text === "/install-resources" || text.startsWith("/install-resources ")) {
2545
+ const args = text.slice("/install-resources".length).trim();
2546
+ this.editor.setText("");
2547
+ await this.handleInstallResourcesCommand(args);
2548
+ return;
2549
+ }
2550
+ if (text === "/config-backup" || text.startsWith("/config-backup ")) {
2551
+ const file = text.slice("/config-backup".length).trim() || undefined;
2552
+ this.editor.setText("");
2553
+ await this.handleConfigBackupCommand(file);
2554
+ return;
2555
+ }
2556
+ if (text === "/config-restore" || text.startsWith("/config-restore ")) {
2557
+ const file = text.slice("/config-restore".length).trim();
2558
+ this.editor.setText("");
2559
+ await this.handleConfigRestoreCommand(file);
2560
+ return;
2561
+ }
2544
2562
  if (text === "/debug") {
2545
2563
  this.handleDebugCommand();
2546
2564
  this.editor.setText("");
@@ -6812,6 +6830,228 @@ export class InteractiveMode {
6812
6830
  await this.handleFatalRuntimeError("Failed to create session", error);
6813
6831
  }
6814
6832
  }
6833
+ copyResourcesRecursively(src, dest, force, stats) {
6834
+ if (!fs.existsSync(src))
6835
+ return;
6836
+ const entries = fs.readdirSync(src, { withFileTypes: true });
6837
+ fs.mkdirSync(dest, { recursive: true });
6838
+ for (const entry of entries) {
6839
+ const srcPath = path.join(src, entry.name);
6840
+ const destPath = path.join(dest, entry.name);
6841
+ if (entry.isDirectory()) {
6842
+ this.copyResourcesRecursively(srcPath, destPath, force, stats);
6843
+ }
6844
+ else if (entry.isFile()) {
6845
+ if (fs.existsSync(destPath) && !force) {
6846
+ stats.skipped.push(destPath);
6847
+ }
6848
+ else {
6849
+ fs.copyFileSync(srcPath, destPath);
6850
+ stats.installed.push(destPath);
6851
+ }
6852
+ }
6853
+ }
6854
+ }
6855
+ async handleInstallResourcesCommand(argsString) {
6856
+ try {
6857
+ const tokens = argsString.split(/\s+/).filter(Boolean);
6858
+ let force = false;
6859
+ let dir = "";
6860
+ for (const t of tokens) {
6861
+ if (t === "--force") {
6862
+ force = true;
6863
+ }
6864
+ else {
6865
+ dir = t;
6866
+ }
6867
+ }
6868
+ if (!dir) {
6869
+ this.showError("Usage: /install-resources <dir> [--force]");
6870
+ return;
6871
+ }
6872
+ const canonical = this.settingsManager.canonicalizePath(dir);
6873
+ if (!canonical || !fs.existsSync(canonical)) {
6874
+ this.showError(`Source directory does not exist: ${dir}`);
6875
+ return;
6876
+ }
6877
+ const trustedRoots = this.settingsManager.getTrustedResourceRoots();
6878
+ const trusted = trustedRoots.includes(canonical);
6879
+ if (!trusted) {
6880
+ const trust = await new Promise((resolve) => {
6881
+ this.showSelector((done) => {
6882
+ const submenu = new SelectSubmenu("Trust external source for installation?", `The directory "${canonical}" contains extensions/resources to install. Extensions can execute arbitrary code on your machine. Do you trust it?`, [
6883
+ {
6884
+ value: "yes",
6885
+ label: "Yes",
6886
+ description: "Trust this directory and proceed with installation.",
6887
+ },
6888
+ { value: "no", label: "No", description: "Do not trust this directory. Abort." },
6889
+ ], "no", (value) => {
6890
+ done();
6891
+ resolve(value === "yes");
6892
+ }, () => {
6893
+ done();
6894
+ resolve(false);
6895
+ });
6896
+ return { component: submenu, focus: submenu.getSelectList() };
6897
+ });
6898
+ });
6899
+ if (!trust) {
6900
+ this.showStatus("Installation aborted. Source directory was not trusted.");
6901
+ return;
6902
+ }
6903
+ this.settingsManager.addTrustedResourceRoot(canonical, "global");
6904
+ }
6905
+ const subdirs = ["skills", "extensions", "prompts", "themes", "profiles"];
6906
+ const stats = { installed: [], skipped: [] };
6907
+ const userAgentDir = getAgentDir();
6908
+ for (const sub of subdirs) {
6909
+ const srcSub = path.join(canonical, sub);
6910
+ const destSub = path.join(userAgentDir, sub);
6911
+ if (fs.existsSync(srcSub)) {
6912
+ this.copyResourcesRecursively(srcSub, destSub, force, stats);
6913
+ }
6914
+ }
6915
+ const installedCount = stats.installed.length;
6916
+ const skippedCount = stats.skipped.length;
6917
+ this.showStatus(`Installation complete: ${installedCount} resources installed, ${skippedCount} skipped.`);
6918
+ await this.handleReloadCommand();
6919
+ }
6920
+ catch (error) {
6921
+ this.showError(error instanceof Error ? error.message : String(error));
6922
+ }
6923
+ }
6924
+ async handleConfigBackupCommand(fileArg) {
6925
+ try {
6926
+ const profilesDir = path.join(getAgentDir(), "profiles");
6927
+ const profiles = {};
6928
+ if (fs.existsSync(profilesDir)) {
6929
+ const entries = fs.readdirSync(profilesDir);
6930
+ for (const entry of entries) {
6931
+ if (entry.endsWith(".json")) {
6932
+ const pPath = path.join(profilesDir, entry);
6933
+ try {
6934
+ const content = fs.readFileSync(pPath, "utf-8");
6935
+ profiles[entry] = JSON.parse(content);
6936
+ }
6937
+ catch {
6938
+ // skip
6939
+ }
6940
+ }
6941
+ }
6942
+ }
6943
+ const backupData = {
6944
+ profiles,
6945
+ settings: {
6946
+ resourceProfiles: this.settingsManager.settings.resourceProfiles,
6947
+ activeResourceProfile: this.settingsManager.settings.activeResourceProfile,
6948
+ externalResourceRoots: this.settingsManager.settings.externalResourceRoots,
6949
+ trustedResourceRoots: this.settingsManager.settings.trustedResourceRoots,
6950
+ },
6951
+ };
6952
+ let targetFile = fileArg;
6953
+ if (!targetFile) {
6954
+ const backupsDir = path.join(getAgentDir(), "backups");
6955
+ fs.mkdirSync(backupsDir, { recursive: true });
6956
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
6957
+ targetFile = path.join(backupsDir, `config-${timestamp}.json`);
6958
+ }
6959
+ else {
6960
+ const resolved = this.settingsManager.canonicalizePath(targetFile);
6961
+ if (resolved) {
6962
+ targetFile = resolved;
6963
+ }
6964
+ }
6965
+ fs.mkdirSync(path.dirname(targetFile), { recursive: true });
6966
+ fs.writeFileSync(targetFile, JSON.stringify(backupData, null, 2), "utf-8");
6967
+ this.showStatus(`Configuration backup saved to ${targetFile}`);
6968
+ }
6969
+ catch (error) {
6970
+ this.showError(error instanceof Error ? error.message : String(error));
6971
+ }
6972
+ }
6973
+ async handleConfigRestoreCommand(fileArg) {
6974
+ try {
6975
+ const trimmed = fileArg.trim();
6976
+ if (!trimmed) {
6977
+ this.showError("Usage: /config-restore <file>");
6978
+ return;
6979
+ }
6980
+ const resolved = this.settingsManager.canonicalizePath(trimmed);
6981
+ if (!resolved || !fs.existsSync(resolved)) {
6982
+ this.showError(`Backup file does not exist: ${trimmed}`);
6983
+ return;
6984
+ }
6985
+ let bundle;
6986
+ try {
6987
+ const content = fs.readFileSync(resolved, "utf-8");
6988
+ bundle = JSON.parse(content);
6989
+ }
6990
+ catch (error) {
6991
+ this.showError(`Failed to parse backup file: ${error instanceof Error ? error.message : String(error)}`);
6992
+ return;
6993
+ }
6994
+ if (!bundle || typeof bundle !== "object") {
6995
+ this.showError("Invalid backup file: must be a JSON object");
6996
+ return;
6997
+ }
6998
+ // Confirm before clobbering
6999
+ const confirm = await new Promise((resolve) => {
7000
+ this.showSelector((done) => {
7001
+ const submenu = new SelectSubmenu("Restore configuration?", "This will overwrite existing local profiles and settings with the backup values. Do you want to continue?", [
7002
+ { value: "yes", label: "Yes", description: "Proceed with restoration." },
7003
+ { value: "no", label: "No", description: "Cancel and abort." },
7004
+ ], "no", (value) => {
7005
+ done();
7006
+ resolve(value === "yes");
7007
+ }, () => {
7008
+ done();
7009
+ resolve(false);
7010
+ });
7011
+ return { component: submenu, focus: submenu.getSelectList() };
7012
+ });
7013
+ });
7014
+ if (!confirm) {
7015
+ this.showStatus("Restore aborted.");
7016
+ return;
7017
+ }
7018
+ // 1. Restore profile files (reusable-file scope)
7019
+ if (bundle.profiles && typeof bundle.profiles === "object") {
7020
+ const profilesDir = path.join(getAgentDir(), "profiles");
7021
+ fs.mkdirSync(profilesDir, { recursive: true });
7022
+ for (const [filename, content] of Object.entries(bundle.profiles)) {
7023
+ const targetPath = path.join(profilesDir, filename);
7024
+ fs.writeFileSync(targetPath, JSON.stringify(content, null, 2), "utf-8");
7025
+ }
7026
+ }
7027
+ // 2. Restore settings
7028
+ if (bundle.settings && typeof bundle.settings === "object") {
7029
+ const bs = bundle.settings;
7030
+ // Global profiles definitions
7031
+ if (bs.resourceProfiles && typeof bs.resourceProfiles === "object") {
7032
+ for (const [name, definition] of Object.entries(bs.resourceProfiles)) {
7033
+ this.settingsManager.setProfileDefinition(name, definition, "global");
7034
+ }
7035
+ }
7036
+ // Active profile selection
7037
+ if (bs.activeResourceProfile) {
7038
+ this.settingsManager.setActiveProfile(bs.activeResourceProfile, "global");
7039
+ }
7040
+ // External roots (trustedRoots are NOT restored, as per SECURITY requirement)
7041
+ if (Array.isArray(bs.externalResourceRoots)) {
7042
+ this.settingsManager.setExternalResourceRoots(bs.externalResourceRoots, "global");
7043
+ const currentTrusted = this.settingsManager.getTrustedResourceRoots();
7044
+ const newTrusted = currentTrusted.filter((r) => !bs.externalResourceRoots.includes(r));
7045
+ this.settingsManager.setTrustedResourceRoots(newTrusted, "global");
7046
+ }
7047
+ }
7048
+ this.showStatus("Configuration restored successfully.");
7049
+ await this.handleReloadCommand();
7050
+ }
7051
+ catch (error) {
7052
+ this.showError(error instanceof Error ? error.message : String(error));
7053
+ }
7054
+ }
6815
7055
  handleDebugCommand() {
6816
7056
  const width = this.ui.terminal.columns;
6817
7057
  const height = this.ui.terminal.rows;