@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.
- package/CHANGELOG.md +8 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +5 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +3 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +12 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +240 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- 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;
|