@astralyn/pi 1.4.7 → 1.4.9

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 (77) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/bundle/chunks/{chunk-YJTSOLP2.js → chunk-3PKXUKTB.js} +90 -90
  3. package/dist/bundle/chunks/{chunk-FODCTZXW.js → chunk-BAGHIP5J.js} +2 -2
  4. package/dist/bundle/chunks/{chunk-PU2IWWXV.js → chunk-DLVLAQEG.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-FYKNSJG6.js → chunk-F66AY3WR.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-MG5XDTXV.js → chunk-LPF7HQ3S.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-RO2VH6UZ.js → chunk-R267VV5T.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-RLNMABLM.js → chunk-RVKT7OUB.js} +1 -1
  9. package/dist/bundle/chunks/{cli-MEL7SGJD.js → cli-MBFCFGI2.js} +1 -1
  10. package/dist/bundle/chunks/{execute-4CWRNHPO.js → execute-P22VMM2H.js} +1 -1
  11. package/dist/bundle/chunks/{runtime-R3X67XMR.js → runtime-3RPOJS5T.js} +1 -1
  12. package/dist/bundle/chunks/{virtual-modules-PKEOKGYI.js → virtual-modules-VKMBQTR2.js} +1 -1
  13. package/dist/bundle/cli.js +1 -1
  14. package/dist/bundle/index.js +1 -1
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/core/package-manager.d.ts +4 -8
  17. package/dist/core/package-manager.d.ts.map +1 -1
  18. package/dist/core/package-manager.js +11 -72
  19. package/dist/core/package-manager.js.map +1 -1
  20. package/dist/core/resource-loader.d.ts +2 -1
  21. package/dist/core/resource-loader.d.ts.map +1 -1
  22. package/dist/core/resource-loader.js +21 -24
  23. package/dist/core/resource-loader.js.map +1 -1
  24. package/dist/core/skill-invocation.d.ts +46 -0
  25. package/dist/core/skill-invocation.d.ts.map +1 -0
  26. package/dist/core/skill-invocation.js +128 -0
  27. package/dist/core/skill-invocation.js.map +1 -0
  28. package/dist/extensions/agent/settings-host.d.ts +33 -0
  29. package/dist/extensions/agent/settings-host.d.ts.map +1 -0
  30. package/dist/extensions/agent/settings-host.js +75 -0
  31. package/dist/extensions/agent/settings-host.js.map +1 -0
  32. package/dist/extensions/agent/settings.d.ts.map +1 -1
  33. package/dist/extensions/agent/settings.js +18 -7
  34. package/dist/extensions/agent/settings.js.map +1 -1
  35. package/dist/extensions/index.d.ts.map +1 -1
  36. package/dist/extensions/index.js +2 -0
  37. package/dist/extensions/index.js.map +1 -1
  38. package/dist/extensions/shell-paths/index.d.ts +8 -0
  39. package/dist/extensions/shell-paths/index.d.ts.map +1 -0
  40. package/dist/extensions/shell-paths/index.js +74 -0
  41. package/dist/extensions/shell-paths/index.js.map +1 -0
  42. package/dist/modes/interactive/chat-viewport.d.ts +5 -2
  43. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  44. package/dist/modes/interactive/chat-viewport.js +72 -12
  45. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  46. package/dist/modes/interactive/components/config-selector.d.ts +10 -8
  47. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  48. package/dist/modes/interactive/components/config-selector.js +51 -121
  49. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  50. package/dist/modes/interactive/components/sticky-user-message.d.ts +23 -0
  51. package/dist/modes/interactive/components/sticky-user-message.d.ts.map +1 -0
  52. package/dist/modes/interactive/components/sticky-user-message.js +58 -0
  53. package/dist/modes/interactive/components/sticky-user-message.js.map +1 -0
  54. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  55. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  56. package/dist/modes/interactive/components/user-message.js +51 -10
  57. package/dist/modes/interactive/components/user-message.js.map +1 -1
  58. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  59. package/dist/modes/interactive/interactive-mode.js +4 -1
  60. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  61. package/dist/modes/interactive/tool-view/chat.d.ts +3 -2
  62. package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -1
  63. package/dist/modes/interactive/tool-view/chat.js +3 -3
  64. package/dist/modes/interactive/tool-view/chat.js.map +1 -1
  65. package/dist/modes/interactive/transcript-layout.d.ts +23 -0
  66. package/dist/modes/interactive/transcript-layout.d.ts.map +1 -0
  67. package/dist/modes/interactive/transcript-layout.js +29 -0
  68. package/dist/modes/interactive/transcript-layout.js.map +1 -0
  69. package/docs/bundled/README.md +1 -0
  70. package/docs/bundled/extensions/shell-paths.md +17 -0
  71. package/docs/docs.json +4 -0
  72. package/docs/packages.md +1 -1
  73. package/docs/settings.md +1 -1
  74. package/docs/skills.md +1 -1
  75. package/docs/usage.md +1 -1
  76. package/npm-shrinkwrap.json +2 -2
  77. package/package.json +1 -1
@@ -5,6 +5,8 @@ import { homedir } from "node:os";
5
5
  import { basename, dirname, join, relative } from "node:path";
6
6
  import { Container, getKeybindings, Input, matchesKey, Spacer, truncateToWidth, visibleWidth, } from "@earendil-works/pi-tui";
7
7
  import { CONFIG_DIR_NAME } from "../../../config.js";
8
+ import { DefaultPackageManager, } from "../../../core/package-manager.js";
9
+ import { matchInvocation, SkillInvocationPolicy, withInvocation } from "../../../core/skill-invocation.js";
8
10
  import { readSkillDisableModelInvocation, resolveSkillEffectiveState, } from "../../../core/skills.js";
9
11
  import { BUILTIN_PATH_PREFIX } from "../../../core/source-info.js";
10
12
  import { canonicalizePath, isLocalPath, resolvePath } from "../../../utils/paths.js";
@@ -19,6 +21,10 @@ function hasResourcePattern(patterns, pattern) {
19
21
  }
20
22
  return false;
21
23
  }
24
+ /** The invocation override that pins a skill state; Off and inherit leave invocation to the defaults. */
25
+ function stateInvocation(state) {
26
+ return state === "on" ? "model-and-user" : state === "user-only" ? "user-only" : undefined;
27
+ }
22
28
  const RESOURCE_TYPES = ["extensions", "skills", "prompts", "themes"];
23
29
  const RESOURCE_TYPE_LABELS = {
24
30
  extensions: "Extensions",
@@ -110,7 +116,6 @@ function buildGroups(resolved, agentDir) {
110
116
  displayName,
111
117
  groupKey,
112
118
  subgroupKey,
113
- skillInvocationOverride: res.skillInvocationOverride,
114
119
  frontmatterDisableModelInvocation: resourceType === "skills" ? readSkillDisableModelInvocation(path) : undefined,
115
120
  });
116
121
  }
@@ -184,7 +189,8 @@ class ResourceList {
184
189
  this.agentDir = agentDir;
185
190
  this.writeScope = writeScope;
186
191
  this.inheritedEnabledByKey = this.buildInheritedEnabledMap(groupsByScope.global);
187
- this.inheritedSkillStateByKey = this.buildInheritedSkillStateMap(groupsByScope.global);
192
+ this.packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });
193
+ this.skillInvocation = new SkillInvocationPolicy(settingsManager, this.packageManager);
188
194
  this.searchInput = new Input();
189
195
  // 8 lines of chrome: top spacer + top border + spacer + header (2 lines) + spacer + bottom spacer + bottom border
190
196
  const chrome = 8;
@@ -211,19 +217,6 @@ class ResourceList {
211
217
  }
212
218
  return result;
213
219
  }
214
- buildInheritedSkillStateMap(groups) {
215
- const result = new Map();
216
- for (const group of groups) {
217
- for (const subgroup of group.subgroups) {
218
- if (subgroup.type !== "skills")
219
- continue;
220
- for (const item of subgroup.items) {
221
- result.set(this.getResourceItemKey(item), this.getSkillEffectiveState(item));
222
- }
223
- }
224
- }
225
- return result;
226
- }
227
220
  buildFlatList() {
228
221
  this.flatItems = [];
229
222
  for (const group of this.groups) {
@@ -301,12 +294,8 @@ class ResourceList {
301
294
  }
302
295
  updateItem(item, enabled) {
303
296
  item.enabled = enabled;
304
- if (this.writeScope === "global") {
297
+ if (this.writeScope === "global")
305
298
  this.inheritedEnabledByKey.set(this.getResourceItemKey(item), enabled);
306
- if (item.resourceType === "skills") {
307
- this.inheritedSkillStateByKey.set(this.getResourceItemKey(item), this.getSkillEffectiveState(item));
308
- }
309
- }
310
299
  // Update in groups too
311
300
  for (const group of this.groups) {
312
301
  for (const subgroup of group.subgroups) {
@@ -434,15 +423,11 @@ class ResourceList {
434
423
  const state = this.getNextProjectSkillOverrideState(item);
435
424
  if (!this.setProjectSkillOverride(item, state))
436
425
  return undefined;
437
- item.skillInvocationOverride =
438
- state === "on" ? "model-and-user" : state === "user-only" ? "user-only" : undefined;
439
426
  return state === "inherit" ? this.getInheritedSkillEffectiveState(item) !== "off" : state !== "off";
440
427
  }
441
428
  const currentState = this.getSkillEffectiveState(item);
442
429
  const nextState = currentState === "on" ? "user-only" : currentState === "user-only" ? "off" : "on";
443
430
  this.setGlobalSkillEffectiveState(item, nextState);
444
- item.skillInvocationOverride =
445
- nextState === "on" ? "model-and-user" : nextState === "user-only" ? "user-only" : undefined;
446
431
  return nextState !== "off";
447
432
  }
448
433
  if (this.writeScope === "project") {
@@ -562,65 +547,42 @@ class ResourceList {
562
547
  this.toggleTopLevelResource(item, enabled);
563
548
  else
564
549
  this.togglePackageResource(item, enabled);
565
- this.setSkillInvocationOverride(item, "user", state === "on" ? "model-and-user" : state === "user-only" ? "user-only" : undefined);
550
+ this.setSkillInvocationOverride(item, "user", stateInvocation(state));
566
551
  }
567
552
  setProjectSkillOverride(item, state) {
568
553
  const loadState = state === "inherit" ? "inherit" : state === "off" ? "unload" : "load";
569
554
  if (!this.setProjectResourceOverride(item, loadState))
570
555
  return false;
571
- this.setSkillInvocationOverride(item, "project", state === "on" ? "model-and-user" : state === "user-only" ? "user-only" : undefined);
556
+ this.setSkillInvocationOverride(item, "project", stateInvocation(state));
572
557
  return true;
573
558
  }
559
+ /** Runs after the load write, which creates the package entry a project override needs. */
574
560
  setSkillInvocationOverride(item, scope, override) {
561
+ const layer = this.skillInvocation.layer(scope, item.metadata);
562
+ if (!layer)
563
+ return;
564
+ const overrides = withInvocation(layer, item.path, override);
575
565
  if (item.metadata.origin === "top-level") {
576
- const settings = scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
577
- const updated = { ...settings.skillInvocationOverrides };
578
- const patterns = this.getTopLevelOverridePatterns(item, scope);
579
- for (const pattern of Object.keys(updated)) {
580
- if (hasResourcePattern(patterns, pattern))
581
- delete updated[pattern];
582
- }
583
- if (override) {
584
- const pattern = scope === "project" && this.isInheritedGlobalItem(item)
585
- ? item.path
586
- : this.getResourcePatternForScope(item, scope);
587
- updated[pattern] = override;
588
- }
589
566
  if (scope === "project")
590
- this.settingsManager.setProjectSkillInvocationOverrides(updated);
567
+ this.settingsManager.setProjectSkillInvocationOverrides(overrides);
591
568
  else
592
- this.settingsManager.setSkillInvocationOverrides(updated);
569
+ this.settingsManager.setSkillInvocationOverrides(overrides);
593
570
  return;
594
571
  }
595
572
  const settings = scope === "project" ? this.settingsManager.getProjectSettings() : this.settingsManager.getGlobalSettings();
596
573
  const packages = [...(settings.packages ?? [])];
597
- const pkgIndex = packages.findIndex((pkg) => this.packageSourceStringMatches(item.metadata.source, this.getItemScope(item), typeof pkg === "string" ? pkg : pkg.source, scope));
598
- if (pkgIndex === -1)
574
+ const pkgIndex = this.skillInvocation.findPackage(scope, item.metadata);
575
+ const current = packages[pkgIndex];
576
+ if (current === undefined || (typeof current === "string" && !overrides))
599
577
  return;
600
- let pkg = packages[pkgIndex];
601
- if (typeof pkg === "string") {
602
- if (!override)
603
- return;
604
- pkg = { source: pkg };
578
+ const pkg = typeof current === "string" ? { source: current } : { ...current };
579
+ pkg.skillInvocationOverrides = overrides;
580
+ if (overrides || RESOURCE_TYPES.some((key) => pkg[key] !== undefined))
605
581
  packages[pkgIndex] = pkg;
606
- }
607
- const updated = { ...pkg.skillInvocationOverrides };
608
- const patterns = this.getPackageSkillInvocationOverridePatterns(item);
609
- for (const pattern of Object.keys(updated)) {
610
- if (hasResourcePattern(patterns, pattern))
611
- delete updated[pattern];
612
- }
613
- const pattern = this.getPackageResourcePattern(item);
614
- if (override)
615
- updated[pattern] = override;
616
- pkg.skillInvocationOverrides = Object.keys(updated).length > 0 ? updated : undefined;
617
- const hasConfiguration = RESOURCE_TYPES.some((key) => pkg[key] !== undefined) || pkg.skillInvocationOverrides !== undefined;
618
- if (!hasConfiguration) {
619
- if (scope === "project" && pkg.autoload === false)
620
- packages.splice(pkgIndex, 1);
621
- else
622
- packages[pkgIndex] = pkg.source;
623
- }
582
+ else if (scope === "project" && pkg.autoload === false)
583
+ packages.splice(pkgIndex, 1);
584
+ else
585
+ packages[pkgIndex] = pkg.source;
624
586
  if (scope === "project")
625
587
  this.settingsManager.setProjectPackages(packages);
626
588
  else
@@ -696,21 +658,19 @@ class ResourceList {
696
658
  ? this.getProjectSkillOverrideState(item) === "inherit"
697
659
  : this.getProjectOverrideState(item) === "inherit";
698
660
  }
661
+ /** The state settings give a skill in the current mode; global mode ignores project settings. */
699
662
  getSkillEffectiveState(item) {
663
+ const scopes = this.writeScope === "project" ? ["project", "user"] : ["user"];
700
664
  return resolveSkillEffectiveState({
701
665
  enabled: item.enabled,
702
- invocationOverride: item.skillInvocationOverride,
666
+ invocationOverride: this.skillInvocation.resolve(item.path, item.metadata, scopes),
703
667
  frontmatterDisableModelInvocation: item.frontmatterDisableModelInvocation,
704
668
  });
705
669
  }
706
670
  getInheritedSkillEffectiveState(item) {
707
- const inherited = this.inheritedSkillStateByKey.get(this.getResourceItemKey(item));
708
- if (inherited)
709
- return inherited;
710
- const userScoped = this.getItemScope(item) === "user";
711
671
  return resolveSkillEffectiveState({
712
- enabled: userScoped ? item.enabled : true,
713
- invocationOverride: userScoped ? item.skillInvocationOverride : undefined,
672
+ enabled: this.getInheritedEnabled(item),
673
+ invocationOverride: this.skillInvocation.resolve(item.path, item.metadata, ["user"]),
714
674
  frontmatterDisableModelInvocation: item.frontmatterDisableModelInvocation,
715
675
  });
716
676
  }
@@ -729,42 +689,15 @@ class ResourceList {
729
689
  getProjectSkillOverrideState(item) {
730
690
  if (this.writeScope !== "project")
731
691
  return "inherit";
732
- let loadState;
733
- let invocationOverrides;
734
- let patterns;
735
- if (item.metadata.origin === "top-level") {
736
- const settings = this.settingsManager.getProjectSettings();
737
- loadState = this.getOverrideStateFromEntries((settings.skills ?? []), this.getTopLevelOverridePatterns(item, "project"), false);
738
- invocationOverrides = settings.skillInvocationOverrides;
739
- patterns = this.getTopLevelOverridePatterns(item, "project");
740
- }
741
- else {
742
- const pkg = this.findMatchingPackageSource(item, "project");
743
- if (typeof pkg !== "object")
744
- return "inherit";
745
- loadState =
746
- pkg.skills === undefined
747
- ? "inherit"
748
- : this.getOverrideStateFromEntries(pkg.skills, this.getPackageSkillInvocationOverridePatterns(item), pkg.autoload !== false);
749
- invocationOverrides = pkg.skillInvocationOverrides;
750
- patterns = this.getPackageSkillInvocationOverridePatterns(item);
751
- }
692
+ const loadState = this.getProjectOverrideState(item);
752
693
  if (loadState === "unload")
753
694
  return "off";
754
- const invocation = this.getSkillInvocationOverrideFromMap(invocationOverrides, patterns);
695
+ const layer = this.skillInvocation.layer("project", item.metadata);
696
+ const invocation = layer ? matchInvocation(layer, item.path).override : undefined;
755
697
  if (invocation)
756
698
  return invocation === "user-only" ? "user-only" : "on";
757
699
  return loadState;
758
700
  }
759
- getSkillInvocationOverrideFromMap(overrides, patterns) {
760
- for (const [pattern, override] of Object.entries(overrides ?? {})) {
761
- if (!hasResourcePattern(patterns, pattern))
762
- continue;
763
- if (override === "model-and-user" || override === "user-only")
764
- return override;
765
- }
766
- return undefined;
767
- }
768
701
  setProjectResourceOverride(item, state) {
769
702
  return item.metadata.origin === "top-level"
770
703
  ? this.setProjectTopLevelOverride(item, state)
@@ -801,7 +734,7 @@ class ResourceList {
801
734
  }
802
735
  setProjectPackageOverride(item, state) {
803
736
  const packages = [...(this.settingsManager.getProjectSettings().packages ?? [])];
804
- let pkgIndex = packages.findIndex((pkg) => this.packageSourceStringMatches(item.metadata.source, this.getItemScope(item), typeof pkg === "string" ? pkg : pkg.source, "project"));
737
+ let pkgIndex = packages.findIndex((pkg) => this.isSamePackage(item.metadata.source, this.getItemScope(item), typeof pkg === "string" ? pkg : pkg.source, "project"));
805
738
  if (pkgIndex === -1) {
806
739
  if (state === "inherit")
807
740
  return false;
@@ -851,7 +784,7 @@ class ResourceList {
851
784
  const entries = pkg[item.resourceType];
852
785
  if (entries === undefined)
853
786
  return "inherit";
854
- return this.getOverrideStateFromEntries(entries, new Set([this.getPackageResourcePattern(item)]), pkg.autoload !== false);
787
+ return this.getOverrideStateFromEntries(entries, this.getPackageOverridePatterns(item), pkg.autoload !== false);
855
788
  }
856
789
  getOverrideStateFromEntries(entries, patterns, emptyArrayIsUnload) {
857
790
  if (entries.length === 0 && emptyArrayIsUnload)
@@ -906,20 +839,16 @@ class ResourceList {
906
839
  const sourcePath = resolvePath(source, this.getTopLevelBaseDir(this.getItemScope(item)), { trim: true });
907
840
  return { source: relative(this.getTopLevelBaseDir("project"), sourcePath) || ".", autoload: false };
908
841
  }
909
- packageSourceStringMatches(leftSource, leftScope, rightSource, rightScope) {
910
- if (leftSource === rightSource)
911
- return true;
912
- if (!isLocalPath(leftSource) || !isLocalPath(rightSource))
913
- return false;
914
- const left = resolvePath(leftSource, this.getTopLevelBaseDir(leftScope), { trim: true });
915
- const right = resolvePath(rightSource, this.getTopLevelBaseDir(rightScope), { trim: true });
916
- return left === right;
842
+ /** Package entries match by the identity package loading dedupes on, so `npm:pkg@1` and `npm:pkg` are one package. */
843
+ isSamePackage(leftSource, leftScope, rightSource, rightScope) {
844
+ return (this.packageManager.getPackageIdentity(leftSource, leftScope) ===
845
+ this.packageManager.getPackageIdentity(rightSource, rightScope));
917
846
  }
918
847
  findMatchingPackageSource(item, targetScope) {
919
848
  const settings = targetScope === "project"
920
849
  ? this.settingsManager.getProjectSettings()
921
850
  : this.settingsManager.getGlobalSettings();
922
- return (settings.packages ?? []).find((pkg) => this.packageSourceStringMatches(item.metadata.source, this.getItemScope(item), typeof pkg === "string" ? pkg : pkg.source, targetScope));
851
+ return (settings.packages ?? []).find((pkg) => this.isSamePackage(item.metadata.source, this.getItemScope(item), typeof pkg === "string" ? pkg : pkg.source, targetScope));
923
852
  }
924
853
  getPatternEntryTarget(entry) {
925
854
  return entry.startsWith("!") || entry.startsWith("+") || entry.startsWith("-") ? entry.slice(1) : entry;
@@ -944,13 +873,14 @@ class ResourceList {
944
873
  const baseDir = item.metadata.baseDir ?? dirname(item.path);
945
874
  return relative(baseDir, item.path);
946
875
  }
947
- getPackageSkillInvocationOverridePatterns(item) {
948
- const baseDir = item.metadata.baseDir ?? dirname(item.path);
949
- const patterns = new Set([this.getPackageResourcePattern(item), item.path]);
950
- if (basename(item.path) === "SKILL.md") {
951
- patterns.add(relative(baseDir, dirname(item.path)));
952
- patterns.add(dirname(item.path));
953
- }
876
+ /** Package filter entries that name an item; a skill can also be named by its absolute path or directory. */
877
+ getPackageOverridePatterns(item) {
878
+ const pattern = this.getPackageResourcePattern(item);
879
+ if (item.resourceType !== "skills")
880
+ return new Set([pattern]);
881
+ const patterns = new Set([pattern, item.path]);
882
+ if (basename(item.path) === "SKILL.md")
883
+ patterns.add(dirname(pattern)).add(dirname(item.path));
954
884
  return patterns;
955
885
  }
956
886
  }