@caupulican/pi-adaptative 0.80.42 → 0.80.44

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 (101) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/bundled-resources/prompts/extensionify.md +20 -0
  3. package/dist/bundled-resources/prompts/learn.md +27 -0
  4. package/dist/bundled-resources/prompts/skillify.md +21 -0
  5. package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +217 -0
  6. package/dist/bundled-resources/skills/skill-architect/SKILL.md +162 -0
  7. package/dist/config.d.ts +17 -0
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +30 -0
  10. package/dist/config.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +37 -2
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +215 -9
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/context-gc.d.ts.map +1 -1
  16. package/dist/core/context-gc.js +27 -5
  17. package/dist/core/context-gc.js.map +1 -1
  18. package/dist/core/extensions/loader.d.ts +10 -3
  19. package/dist/core/extensions/loader.d.ts.map +1 -1
  20. package/dist/core/extensions/loader.js +38 -7
  21. package/dist/core/extensions/loader.js.map +1 -1
  22. package/dist/core/extensions/runner.d.ts +6 -0
  23. package/dist/core/extensions/runner.d.ts.map +1 -1
  24. package/dist/core/extensions/runner.js +53 -6
  25. package/dist/core/extensions/runner.js.map +1 -1
  26. package/dist/core/extensions/types.d.ts +16 -2
  27. package/dist/core/extensions/types.d.ts.map +1 -1
  28. package/dist/core/extensions/types.js.map +1 -1
  29. package/dist/core/profile-registry.d.ts +39 -0
  30. package/dist/core/profile-registry.d.ts.map +1 -0
  31. package/dist/core/profile-registry.js +230 -0
  32. package/dist/core/profile-registry.js.map +1 -0
  33. package/dist/core/profile-resource-selection.d.ts +19 -0
  34. package/dist/core/profile-resource-selection.d.ts.map +1 -0
  35. package/dist/core/profile-resource-selection.js +84 -0
  36. package/dist/core/profile-resource-selection.js.map +1 -0
  37. package/dist/core/resource-loader.d.ts +33 -3
  38. package/dist/core/resource-loader.d.ts.map +1 -1
  39. package/dist/core/resource-loader.js +68 -11
  40. package/dist/core/resource-loader.js.map +1 -1
  41. package/dist/core/settings-manager.d.ts +44 -2
  42. package/dist/core/settings-manager.d.ts.map +1 -1
  43. package/dist/core/settings-manager.js +557 -27
  44. package/dist/core/settings-manager.js.map +1 -1
  45. package/dist/core/skills.d.ts +5 -0
  46. package/dist/core/skills.d.ts.map +1 -1
  47. package/dist/core/skills.js +2 -2
  48. package/dist/core/skills.js.map +1 -1
  49. package/dist/core/slash-commands.d.ts.map +1 -1
  50. package/dist/core/slash-commands.js +1 -0
  51. package/dist/core/slash-commands.js.map +1 -1
  52. package/dist/core/system-prompt.d.ts.map +1 -1
  53. package/dist/core/system-prompt.js +5 -17
  54. package/dist/core/system-prompt.js.map +1 -1
  55. package/dist/core/tools/extensionify.d.ts +33 -0
  56. package/dist/core/tools/extensionify.d.ts.map +1 -0
  57. package/dist/core/tools/extensionify.js +146 -0
  58. package/dist/core/tools/extensionify.js.map +1 -0
  59. package/dist/core/tools/index.d.ts +10 -1
  60. package/dist/core/tools/index.d.ts.map +1 -1
  61. package/dist/core/tools/index.js +36 -1
  62. package/dist/core/tools/index.js.map +1 -1
  63. package/dist/core/tools/skill-audit.d.ts +63 -0
  64. package/dist/core/tools/skill-audit.d.ts.map +1 -0
  65. package/dist/core/tools/skill-audit.js +175 -0
  66. package/dist/core/tools/skill-audit.js.map +1 -0
  67. package/dist/core/tools/skillify.d.ts +30 -0
  68. package/dist/core/tools/skillify.d.ts.map +1 -0
  69. package/dist/core/tools/skillify.js +91 -0
  70. package/dist/core/tools/skillify.js.map +1 -0
  71. package/dist/index.d.ts +1 -0
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +4 -0
  74. package/dist/index.js.map +1 -1
  75. package/dist/modes/interactive/components/profile-resource-editor.d.ts +50 -0
  76. package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -0
  77. package/dist/modes/interactive/components/profile-resource-editor.js +232 -0
  78. package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -0
  79. package/dist/modes/interactive/components/profile-selector.d.ts +8 -0
  80. package/dist/modes/interactive/components/profile-selector.d.ts.map +1 -0
  81. package/dist/modes/interactive/components/profile-selector.js +77 -0
  82. package/dist/modes/interactive/components/profile-selector.js.map +1 -0
  83. package/dist/modes/interactive/components/settings-selector.d.ts +7 -0
  84. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/settings-selector.js +62 -0
  86. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  87. package/dist/modes/interactive/interactive-mode.d.ts +12 -0
  88. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  89. package/dist/modes/interactive/interactive-mode.js +362 -24
  90. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  91. package/docs/settings.md +20 -1
  92. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  93. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  94. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  95. package/examples/extensions/sandbox/package-lock.json +2 -2
  96. package/examples/extensions/sandbox/package.json +1 -1
  97. package/examples/extensions/with-deps/package-lock.json +2 -2
  98. package/examples/extensions/with-deps/package.json +1 -1
  99. package/examples/sdk/12-full-control.ts +4 -0
  100. package/npm-shrinkwrap.json +12 -12
  101. package/package.json +6 -6
@@ -29,6 +29,7 @@ import { exportSessionToHtml } from "./export-html/index.js";
29
29
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
30
30
  import { createCoreDiagnosticsToolDefinitions } from "./extensions/builtin.js";
31
31
  import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
32
+ import { disposeExtensionEventSubscriptions } from "./extensions/loader.js";
32
33
  import { emitSessionShutdownEvent } from "./extensions/runner.js";
33
34
  import { compactToolResultDetailsForRetention } from "./message-retention.js";
34
35
  import { expandPromptTemplate } from "./prompt-templates.js";
@@ -71,6 +72,7 @@ export class AgentSession {
71
72
  // Event subscription state
72
73
  _unsubscribeAgent;
73
74
  _eventListeners = [];
75
+ _extensionsChangedListeners = [];
74
76
  /** Tracks pending steering messages for UI display. Removed when delivered. */
75
77
  _steeringMessages = [];
76
78
  /** Tracks pending follow-up messages for UI display. Removed when delivered. */
@@ -579,6 +581,33 @@ export class AgentSession {
579
581
  }
580
582
  };
581
583
  }
584
+ /**
585
+ * Subscribe to extensions changed events (load/unload live).
586
+ * Returns unsubscribe function for this listener.
587
+ */
588
+ onExtensionsChanged(cb) {
589
+ this._extensionsChangedListeners.push(cb);
590
+ return () => {
591
+ const index = this._extensionsChangedListeners.indexOf(cb);
592
+ if (index !== -1) {
593
+ this._extensionsChangedListeners.splice(index, 1);
594
+ }
595
+ };
596
+ }
597
+ /**
598
+ * Notify all extensions-changed listeners.
599
+ * Called after successful load/unload operations.
600
+ */
601
+ _notifyExtensionsChanged() {
602
+ for (const listener of this._extensionsChangedListeners) {
603
+ try {
604
+ listener();
605
+ }
606
+ catch {
607
+ // Suppress errors from listeners to avoid cascading failures
608
+ }
609
+ }
610
+ }
582
611
  /**
583
612
  * Temporarily disconnect from agent events.
584
613
  * User listeners are preserved and will receive events again after resubscribe().
@@ -756,9 +785,7 @@ export class AgentSession {
756
785
  _buildSelfModificationPrompt() {
757
786
  const settings = this.settingsManager.getSelfModificationSettings();
758
787
  if (!settings.enabled) {
759
- return `Pi self-modification guardrails (local setting inactive):
760
- - Do not modify Pi core, the installed Pi runtime, or pi-adaptative harness source for self-evolution.
761
- - If self-modification is needed, ask the user to enable \`selfModification.enabled\` and set \`selfModification.sourcePaths\` (or legacy \`selfModification.sourcePath\`) to the pi-adaptative source checkout.`;
788
+ return undefined;
762
789
  }
763
790
  // Resolve from an ordered candidate list first (portable WSL/Termux switching
764
791
  // from settings alone), then fall back to the legacy single sourcePath.
@@ -796,7 +823,7 @@ export class AgentSession {
796
823
  _buildAutonomyPrompt() {
797
824
  const autoLearn = this.settingsManager.getAutoLearnSettings();
798
825
  const autonomy = this.settingsManager.getAutonomySettings();
799
- if (!autoLearn.enabled && autonomy.mode === "off") {
826
+ if (!autoLearn.enabled && autonomy.mode !== "full") {
800
827
  return undefined;
801
828
  }
802
829
  const reflection = autoLearn.reflectionReview ?? autonomy.mode !== "off";
@@ -1339,17 +1366,20 @@ export class AgentSession {
1339
1366
  * Validates that auth is configured, saves to session and settings.
1340
1367
  * @throws Error if no auth is configured for the model
1341
1368
  */
1342
- async setModel(model) {
1369
+ async setModel(model, options = {}) {
1343
1370
  if (!this._modelRegistry.hasConfiguredAuth(model)) {
1344
1371
  throw new Error(`No API key for ${model.provider}/${model.id}`);
1345
1372
  }
1373
+ const persistSettings = options.persistSettings ?? true;
1346
1374
  const previousModel = this.model;
1347
1375
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1348
1376
  this.agent.state.model = model;
1349
1377
  this.sessionManager.appendModelChange(model.provider, model.id);
1350
- this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1378
+ if (persistSettings) {
1379
+ this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1380
+ }
1351
1381
  // Re-clamp thinking level for new model's capabilities
1352
- this.setThinkingLevel(thinkingLevel);
1382
+ this.setThinkingLevel(thinkingLevel, { persistSettings });
1353
1383
  await this._emitModelSelect(model, previousModel, "set");
1354
1384
  }
1355
1385
  /**
@@ -1416,16 +1446,17 @@ export class AgentSession {
1416
1446
  * Clamps to model capabilities based on available thinking levels.
1417
1447
  * Saves to session and settings only if the level actually changes.
1418
1448
  */
1419
- setThinkingLevel(level) {
1449
+ setThinkingLevel(level, options = {}) {
1420
1450
  const availableLevels = this.getAvailableThinkingLevels();
1421
1451
  const effectiveLevel = availableLevels.includes(level) ? level : this._clampThinkingLevel(level, availableLevels);
1422
1452
  // Only persist if actually changing
1423
1453
  const previousLevel = this.agent.state.thinkingLevel;
1424
1454
  const isChanging = effectiveLevel !== previousLevel;
1455
+ const persistSettings = options.persistSettings ?? true;
1425
1456
  this.agent.state.thinkingLevel = effectiveLevel;
1426
1457
  if (isChanging) {
1427
1458
  this.sessionManager.appendThinkingLevelChange(effectiveLevel);
1428
- if (this.supportsThinking() || effectiveLevel !== "off") {
1459
+ if (persistSettings && (this.supportsThinking() || effectiveLevel !== "off")) {
1429
1460
  this.settingsManager.setDefaultThinkingLevel(effectiveLevel);
1430
1461
  }
1431
1462
  this._emit({ type: "thinking_level_changed", level: effectiveLevel });
@@ -2319,6 +2350,181 @@ export class AgentSession {
2319
2350
  throw error;
2320
2351
  }
2321
2352
  }
2353
+ /**
2354
+ * Unload a single extension without full reload.
2355
+ * Runs the extension's session_shutdown lifecycle, unregisters its providers,
2356
+ * disposes its event subscriptions, and rebuilds the runtime.
2357
+ * Falls back to full reload on error.
2358
+ */
2359
+ async unloadExtensionLive(extensionPath) {
2360
+ if (this.isStreaming) {
2361
+ throw new Error("Cannot unload extension while the agent is streaming or a tool call is active");
2362
+ }
2363
+ if (this.isCompacting) {
2364
+ throw new Error("Cannot unload extension while context compaction or branch summarization is active");
2365
+ }
2366
+ const ext = this._resourceLoader.getLoadedExtension(extensionPath);
2367
+ if (!ext) {
2368
+ return; // Nothing to unload
2369
+ }
2370
+ const previousRunner = this._extensionRunner;
2371
+ try {
2372
+ // Run session_shutdown lifecycle for this extension only
2373
+ await this._extensionRunner.emitToExtension(ext, { type: "session_shutdown", reason: "unload" });
2374
+ // Unregister its providers (keyed by the extension's own path, as registered)
2375
+ const runtime = this._resourceLoader.getExtensions().runtime;
2376
+ for (const name of runtime.getProvidersForExtension(ext.path)) {
2377
+ runtime.unregisterProvider(name, ext.path);
2378
+ }
2379
+ // Dispose its event subscriptions and run disposers
2380
+ await disposeExtensionEventSubscriptions([ext]);
2381
+ // Remove from loaded extensions
2382
+ this._resourceLoader.removeLoadedExtension(extensionPath);
2383
+ // Rebuild runtime with new extension set
2384
+ const activeToolNames = this.getActiveToolNames();
2385
+ const previousFlagValues = previousRunner.getFlagValues();
2386
+ this._buildRuntime({
2387
+ activeToolNames,
2388
+ flagValues: previousFlagValues,
2389
+ includeAllExtensionTools: true,
2390
+ });
2391
+ previousRunner.invalidate();
2392
+ // Notify extensions-changed listeners
2393
+ this._notifyExtensionsChanged();
2394
+ }
2395
+ catch (error) {
2396
+ // Fall back to full reload on error
2397
+ try {
2398
+ await this.reload();
2399
+ }
2400
+ catch {
2401
+ // Suppress nested error; original error will be thrown below
2402
+ }
2403
+ throw error;
2404
+ }
2405
+ }
2406
+ /**
2407
+ * Load a single extension without full reload.
2408
+ * Loads the extension with fresh import, rebuilds the runtime,
2409
+ * and runs the extension's session_start lifecycle.
2410
+ * Falls back to full reload on error.
2411
+ */
2412
+ async loadExtensionLive(extensionPath) {
2413
+ if (this.isStreaming) {
2414
+ throw new Error("Cannot load extension while the agent is streaming or a tool call is active");
2415
+ }
2416
+ if (this.isCompacting) {
2417
+ throw new Error("Cannot load extension while context compaction or branch summarization is active");
2418
+ }
2419
+ const previousRunner = this._extensionRunner;
2420
+ try {
2421
+ // Load the extension with fresh import
2422
+ const { extension, error } = await this._resourceLoader.loadSingleExtension(extensionPath);
2423
+ if (error || !extension) {
2424
+ throw new Error(error || `Failed to load extension: ${extensionPath}`);
2425
+ }
2426
+ // Rebuild runtime to aggregate tools/commands/handlers/providers
2427
+ const activeToolNames = this.getActiveToolNames();
2428
+ const previousFlagValues = previousRunner.getFlagValues();
2429
+ this._buildRuntime({
2430
+ activeToolNames,
2431
+ flagValues: previousFlagValues,
2432
+ includeAllExtensionTools: true,
2433
+ });
2434
+ // Run session_start lifecycle for the new extension only
2435
+ await this._extensionRunner.emitToExtension(extension, { type: "session_start", reason: "load" });
2436
+ // Notify extensions-changed listeners
2437
+ this._notifyExtensionsChanged();
2438
+ }
2439
+ catch (error) {
2440
+ // Fall back to full reload on error
2441
+ try {
2442
+ await this.reload();
2443
+ }
2444
+ catch {
2445
+ // Suppress nested error; original error will be thrown below
2446
+ }
2447
+ throw error;
2448
+ }
2449
+ }
2450
+ /**
2451
+ * Reconcile loaded extensions with the active profile.
2452
+ * Loads extensions that should be enabled but aren't, and unloads extensions that shouldn't be.
2453
+ * Falls back to full reload if any individual load/unload fails.
2454
+ */
2455
+ async reconcileLoadedExtensions() {
2456
+ if (this.isStreaming) {
2457
+ throw new Error("Cannot reconcile extensions while the agent is streaming or a tool call is active");
2458
+ }
2459
+ if (this.isCompacting) {
2460
+ throw new Error("Cannot reconcile extensions while context compaction or branch summarization is active");
2461
+ }
2462
+ try {
2463
+ // Get all discoverable extension paths
2464
+ const allDiscoverablePaths = await this._resourceLoader.getDiscoverableExtensionPaths();
2465
+ // Get the target enabled set based on profile filters
2466
+ const targetEnabledSet = new Set();
2467
+ for (const path of allDiscoverablePaths) {
2468
+ if (this.settingsManager.isResourceAllowedByProfile("extensions", path)) {
2469
+ targetEnabledSet.add(path);
2470
+ }
2471
+ }
2472
+ // Get currently loaded set
2473
+ const loadedExtensions = this._resourceLoader.getExtensions().extensions;
2474
+ const loadedSet = new Set();
2475
+ for (const ext of loadedExtensions) {
2476
+ loadedSet.add(ext.path);
2477
+ }
2478
+ // Collect unloads and loads
2479
+ const toUnload = [];
2480
+ const toLoad = [];
2481
+ for (const path of loadedSet) {
2482
+ if (!targetEnabledSet.has(path)) {
2483
+ toUnload.push(path);
2484
+ }
2485
+ }
2486
+ for (const path of targetEnabledSet) {
2487
+ if (!loadedSet.has(path)) {
2488
+ toLoad.push(path);
2489
+ }
2490
+ }
2491
+ // Apply unloads first, then loads, to minimize churn
2492
+ // Collect errors but continue through all operations
2493
+ const errors = [];
2494
+ for (const path of toUnload) {
2495
+ try {
2496
+ await this.unloadExtensionLive(path);
2497
+ }
2498
+ catch (error) {
2499
+ errors.push(error instanceof Error ? error : new Error(String(error)));
2500
+ }
2501
+ }
2502
+ for (const path of toLoad) {
2503
+ try {
2504
+ await this.loadExtensionLive(path);
2505
+ }
2506
+ catch (error) {
2507
+ errors.push(error instanceof Error ? error : new Error(String(error)));
2508
+ }
2509
+ }
2510
+ // If any errors occurred, throw the first one (already fell back to full reload in load/unload)
2511
+ if (errors.length > 0) {
2512
+ throw errors[0];
2513
+ }
2514
+ // Single notification at the end
2515
+ this._notifyExtensionsChanged();
2516
+ }
2517
+ catch (error) {
2518
+ // Fall back to full reload on error
2519
+ try {
2520
+ await this.reload();
2521
+ }
2522
+ catch {
2523
+ // Suppress nested error; original error will be thrown below
2524
+ }
2525
+ throw error;
2526
+ }
2527
+ }
2322
2528
  // =========================================================================
2323
2529
  // Auto-Retry
2324
2530
  // =========================================================================