@diegopetrucci/pi-extensions 0.1.53 → 0.1.54

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 (68) hide show
  1. package/.pi-fleet-tested-version +1 -1
  2. package/README.md +35 -15
  3. package/extensions/agent-workflow-audit/.pi-fleet-tested-version +1 -1
  4. package/extensions/agent-workflow-audit/index.ts +12 -0
  5. package/extensions/agent-workflow-audit/package.json +1 -1
  6. package/extensions/annotate-git-diff/.pi-fleet-tested-version +1 -1
  7. package/extensions/annotate-git-diff/git.ts +1 -0
  8. package/extensions/annotate-git-diff/index.ts +1 -1
  9. package/extensions/annotate-git-diff/package.json +1 -1
  10. package/extensions/annotate-git-diff/prompt.ts +2 -1
  11. package/extensions/annotate-last-message/.pi-fleet-tested-version +1 -1
  12. package/extensions/annotate-last-message/index.ts +1 -1
  13. package/extensions/annotate-last-message/package.json +1 -1
  14. package/extensions/brrr/.pi-fleet-tested-version +1 -1
  15. package/extensions/brrr/index.ts +4 -3
  16. package/extensions/brrr/package.json +1 -1
  17. package/extensions/claude-fast/.pi-fleet-tested-version +1 -1
  18. package/extensions/claude-fast/package.json +1 -1
  19. package/extensions/confirm-destructive/.pi-fleet-tested-version +1 -1
  20. package/extensions/confirm-destructive/package.json +1 -1
  21. package/extensions/context-cap/.pi-fleet-tested-version +1 -1
  22. package/extensions/context-cap/package.json +1 -1
  23. package/extensions/context-inspector/.pi-fleet-tested-version +1 -1
  24. package/extensions/context-inspector/index.ts +5 -0
  25. package/extensions/context-inspector/package.json +1 -1
  26. package/extensions/contrarian/.pi-fleet-tested-version +1 -1
  27. package/extensions/contrarian/index.ts +35 -3
  28. package/extensions/contrarian/package.json +1 -1
  29. package/extensions/dirty-repo-guard/.pi-fleet-tested-version +1 -1
  30. package/extensions/dirty-repo-guard/package.json +1 -1
  31. package/extensions/git-footer/.pi-fleet-tested-version +1 -1
  32. package/extensions/git-footer/index.ts +42 -14
  33. package/extensions/git-footer/package.json +1 -1
  34. package/extensions/gnosis/.pi-fleet-tested-version +1 -1
  35. package/extensions/gnosis/package.json +1 -1
  36. package/extensions/illustrations-to-explain-things/.pi-fleet-tested-version +1 -1
  37. package/extensions/illustrations-to-explain-things/package.json +1 -1
  38. package/extensions/inline-bash/.pi-fleet-tested-version +1 -1
  39. package/extensions/inline-bash/package.json +1 -1
  40. package/extensions/librarian/.pi-fleet-tested-version +1 -1
  41. package/extensions/librarian/index.ts +7 -0
  42. package/extensions/librarian/package.json +1 -1
  43. package/extensions/minimal-footer/.pi-fleet-tested-version +1 -1
  44. package/extensions/minimal-footer/index.ts +132 -72
  45. package/extensions/minimal-footer/package.json +1 -1
  46. package/extensions/notify/.pi-fleet-tested-version +1 -1
  47. package/extensions/notify/package.json +1 -1
  48. package/extensions/openai-fast/.pi-fleet-tested-version +1 -1
  49. package/extensions/openai-fast/package.json +1 -1
  50. package/extensions/oracle/.pi-fleet-tested-version +1 -1
  51. package/extensions/oracle/index.ts +21 -2
  52. package/extensions/oracle/package.json +1 -1
  53. package/extensions/permission-gate/.pi-fleet-tested-version +1 -1
  54. package/extensions/permission-gate/index.ts +5 -1
  55. package/extensions/permission-gate/package.json +1 -1
  56. package/extensions/quiet-tools/.pi-fleet-tested-version +1 -1
  57. package/extensions/quiet-tools/index.ts +6 -0
  58. package/extensions/quiet-tools/package.json +1 -1
  59. package/extensions/review/.pi-fleet-tested-version +1 -1
  60. package/extensions/review/index.ts +251 -197
  61. package/extensions/review/package.json +1 -1
  62. package/extensions/todo/.pi-fleet-tested-version +1 -1
  63. package/extensions/todo/index.ts +1 -1
  64. package/extensions/todo/package.json +1 -1
  65. package/extensions/triage-comments/.pi-fleet-tested-version +1 -1
  66. package/extensions/triage-comments/index.ts +25 -3
  67. package/extensions/triage-comments/package.json +1 -1
  68. package/package.json +6 -5
@@ -154,6 +154,11 @@ type CommandRunner = (
154
154
  options: { cwd: string; signal: AbortSignal },
155
155
  ) => Promise<CommandResult>;
156
156
 
157
+ type RunCommandSafelyResult =
158
+ | { kind: "ok"; result: CommandResult }
159
+ | { kind: "transient" }
160
+ | { kind: "unavailable" };
161
+
157
162
  type TimerHandle = unknown;
158
163
 
159
164
  type Clock = {
@@ -566,6 +571,10 @@ function defaultClock(): Clock {
566
571
  };
567
572
  }
568
573
 
574
+ function isCommandUnavailableError(error: unknown): boolean {
575
+ return !!error && typeof error === "object" && (error as { code?: unknown }).code === "ENOENT";
576
+ }
577
+
569
578
  class GitFooterCache {
570
579
  private readonly cwd: () => string;
571
580
  private readonly canRun: () => boolean;
@@ -636,7 +645,7 @@ class GitFooterCache {
636
645
  const result = await this.fetchGitStatus();
637
646
  if (this.disposed) return;
638
647
  if (result.kind === "transient") return;
639
- if (result.kind === "not-a-repo") {
648
+ if (result.kind === "not-a-repo" || result.kind === "unavailable") {
640
649
  this.statusSnapshot = undefined;
641
650
  this.pullRequestSnapshot = undefined;
642
651
  this.lastSeenBranch = undefined;
@@ -662,8 +671,8 @@ class GitFooterCache {
662
671
 
663
672
  const pr = await this.fetchPullRequest();
664
673
  if (this.disposed) return;
665
- if (pr !== undefined) this.pullRequestSnapshot = pr;
666
- else if (branchChanged) this.pullRequestSnapshot = undefined;
674
+ if (pr.kind === "ok") this.pullRequestSnapshot = pr.pullRequest;
675
+ else if (pr.kind === "not-found" || pr.kind === "unavailable") this.pullRequestSnapshot = undefined;
667
676
 
668
677
  this.emitChangeIfSnapshotsChanged(previousStatusSnapshot, previousPullRequestSnapshot);
669
678
  }
@@ -690,32 +699,40 @@ class GitFooterCache {
690
699
  | { kind: "ok"; status: GitStatusSnapshot }
691
700
  | { kind: "not-a-repo" }
692
701
  | { kind: "transient" }
702
+ | { kind: "unavailable" }
693
703
  > {
694
704
  const result = await this.runCommandSafely("git", GIT_STATUS_ARGS, this.gitTimeoutMs);
695
- if (!result) return { kind: "transient" };
696
- if (result.exitCode !== 0) return { kind: "not-a-repo" };
697
- return { kind: "ok", status: parseGitStatusPorcelainV2(result.stdout) };
705
+ if (result.kind !== "ok") return result;
706
+ if (result.result.exitCode !== 0) return { kind: "not-a-repo" };
707
+ return { kind: "ok", status: parseGitStatusPorcelainV2(result.result.stdout) };
698
708
  }
699
709
 
700
- private async fetchPullRequest(): Promise<PullRequestSnapshot | undefined> {
710
+ private async fetchPullRequest(): Promise<
711
+ | { kind: "ok"; pullRequest: PullRequestSnapshot | undefined }
712
+ | { kind: "not-found" }
713
+ | { kind: "transient" }
714
+ | { kind: "unavailable" }
715
+ > {
701
716
  const result = await this.runCommandSafely("gh", GH_PR_VIEW_ARGS, this.ghTimeoutMs);
702
- if (!result || result.exitCode !== 0) return undefined;
703
- return parsePullRequestJson(result.stdout);
717
+ if (result.kind !== "ok") return result;
718
+ if (result.result.exitCode !== 0) return { kind: "not-found" };
719
+ return { kind: "ok", pullRequest: parsePullRequestJson(result.result.stdout) };
704
720
  }
705
721
 
706
722
  private async runCommandSafely(
707
723
  command: string,
708
724
  args: readonly string[],
709
725
  timeoutMs: number,
710
- ): Promise<CommandResult | undefined> {
711
- if (this.disposed) return undefined;
726
+ ): Promise<RunCommandSafelyResult> {
727
+ if (this.disposed) return { kind: "transient" };
712
728
  const controller = new AbortController();
713
729
  this.inflightControllers.add(controller);
714
730
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
715
731
  try {
716
- return await this.runner(command, args, { cwd: this.cwd(), signal: controller.signal });
717
- } catch {
718
- return undefined;
732
+ const result = await this.runner(command, args, { cwd: this.cwd(), signal: controller.signal });
733
+ return { kind: "ok", result };
734
+ } catch (error) {
735
+ return isCommandUnavailableError(error) ? { kind: "unavailable" } : { kind: "transient" };
719
736
  } finally {
720
737
  clearTimeout(timeoutId);
721
738
  this.inflightControllers.delete(controller);
@@ -734,6 +751,76 @@ class GitFooterCache {
734
751
  }
735
752
  }
736
753
 
754
+ function renderFooterLines(options: {
755
+ width: number;
756
+ cwd: string;
757
+ config: MinimalFooterConfig;
758
+ branch: string;
759
+ gitStatus?: string;
760
+ contextUsage?: { percent?: number | null; tokens?: number | null };
761
+ modelId?: string;
762
+ modelProvider?: string;
763
+ thinkingLevel: string;
764
+ theme: { fg(color: DumbZoneColor | "dim", text: string): string };
765
+ usageSnapshot?: UsageSnapshot;
766
+ }): string[] {
767
+ const repo = basename(options.cwd);
768
+ const branchText = options.gitStatus
769
+ ? [options.branch, options.gitStatus].filter(Boolean).join(" · ")
770
+ : options.branch;
771
+
772
+ const context = options.contextUsage?.percent == null
773
+ ? "?"
774
+ : `${options.contextUsage.percent.toFixed(1)}%`;
775
+ const dumbZone = options.config.context.dumbZone;
776
+ const inDumbZone = dumbZone.enabled
777
+ && (options.contextUsage?.tokens ?? 0) > dumbZone.thresholdTokens;
778
+ const usageSummary = shouldShowCodexUsage(options.config)
779
+ && isOpenAICodexProvider(options.modelProvider)
780
+ ? formatUsageSummary(options.usageSnapshot, options.config.codexUsage.windows)
781
+ : undefined;
782
+
783
+ const model = options.modelId ?? "no-model";
784
+ const modelText = options.thinkingLevel === "off"
785
+ ? model
786
+ : `${model} ${options.thinkingLevel}`;
787
+
788
+ const branchStyled = options.theme.fg("dim", branchText);
789
+ const repoStyled = options.theme.fg("dim", repo);
790
+ const contextParts: string[] = [];
791
+ if (options.config.context.showPercent) contextParts.push(options.theme.fg("dim", context));
792
+ if (inDumbZone) contextParts.push(options.theme.fg(dumbZone.color, dumbZone.label));
793
+ if (usageSummary) contextParts.push(options.theme.fg("dim", usageSummary));
794
+ if (shouldShowExperimentalMarker(options.config)) {
795
+ const marker = options.config.experimentalMarker;
796
+ contextParts.push(options.theme.fg(marker.color, marker.label));
797
+ }
798
+ const contextStyled = contextParts.join(options.theme.fg("dim", " · "));
799
+ const modelStyled = options.theme.fg("dim", modelText);
800
+
801
+ const renderSplitLine = (left: string, right: string): string => {
802
+ const gap = " ".repeat(Math.max(2, options.width - visibleWidth(left) - visibleWidth(right)));
803
+ return truncateToWidth(left + gap + right, options.width);
804
+ };
805
+
806
+ const line1Fits = visibleWidth(branchStyled) + visibleWidth(repoStyled) + 2 <= options.width;
807
+ const line2Fits = visibleWidth(contextStyled) + visibleWidth(modelStyled) + 2 <= options.width;
808
+
809
+ if (line1Fits && line2Fits) {
810
+ return [
811
+ renderSplitLine(branchStyled, repoStyled),
812
+ renderSplitLine(contextStyled, modelStyled),
813
+ ];
814
+ }
815
+
816
+ return [
817
+ truncateToWidth(branchStyled, options.width),
818
+ truncateToWidth(repoStyled, options.width),
819
+ truncateToWidth(contextStyled, options.width),
820
+ truncateToWidth(modelStyled, options.width),
821
+ ];
822
+ }
823
+
737
824
  function clearUsageState(state: UsageSessionState): void {
738
825
  state.snapshot = undefined;
739
826
  state.lastFetchedAt = undefined;
@@ -842,64 +929,24 @@ export default function (pi: ExtensionAPI) {
842
929
  },
843
930
  invalidate() {},
844
931
  render(width: number): string[] {
845
- const repo = basename(ctx.cwd);
846
- const gitStatus = shouldShowGitStatus(state.config)
847
- ? formatGitFooterStatus(
848
- state.gitCache?.getStatusSnapshot(),
849
- state.gitCache?.getPullRequestSnapshot(),
850
- )
851
- : undefined;
852
- const branch = footerData.getGitBranch()
853
- ?? state.gitCache?.getStatusSnapshot()?.branch
854
- ?? "";
855
- const branchText = gitStatus ? [branch, gitStatus].filter(Boolean).join(" · ") : branch;
856
-
857
- const usage = ctx.getContextUsage();
858
- const context = usage?.percent == null ? "?" : `${usage.percent.toFixed(1)}%`;
859
- const dumbZone = state.config.context.dumbZone;
860
- const inDumbZone = dumbZone.enabled && (usage?.tokens ?? 0) > dumbZone.thresholdTokens;
861
- const usageSummary = shouldShowCodexUsage(state.config) && isOpenAICodexProvider(ctx.model?.provider)
862
- ? formatUsageSummary(state.snapshot, state.config.codexUsage.windows)
863
- : undefined;
864
-
865
- const model = ctx.model?.id ?? "no-model";
866
- const thinking = pi.getThinkingLevel();
867
- const modelText = thinking === "off" ? model : `${model} ${thinking}`;
868
-
869
- const branchStyled = theme.fg("dim", branchText);
870
- const repoStyled = theme.fg("dim", repo);
871
- const contextParts: string[] = [];
872
- if (state.config.context.showPercent) contextParts.push(theme.fg("dim", context));
873
- if (inDumbZone) contextParts.push(theme.fg(dumbZone.color, dumbZone.label));
874
- if (usageSummary) contextParts.push(theme.fg("dim", usageSummary));
875
- if (shouldShowExperimentalMarker(state.config)) {
876
- const marker = state.config.experimentalMarker;
877
- contextParts.push(theme.fg(marker.color, marker.label));
878
- }
879
- const contextStyled = contextParts.join(theme.fg("dim", " · "));
880
- const modelStyled = theme.fg("dim", modelText);
881
-
882
- const renderSplitLine = (left: string, right: string): string => {
883
- const gap = " ".repeat(Math.max(2, width - visibleWidth(left) - visibleWidth(right)));
884
- return truncateToWidth(left + gap + right, width);
885
- };
886
-
887
- const line1Fits = visibleWidth(branchStyled) + visibleWidth(repoStyled) + 2 <= width;
888
- const line2Fits = visibleWidth(contextStyled) + visibleWidth(modelStyled) + 2 <= width;
889
-
890
- if (line1Fits && line2Fits) {
891
- return [
892
- renderSplitLine(branchStyled, repoStyled),
893
- renderSplitLine(contextStyled, modelStyled),
894
- ];
895
- }
896
-
897
- return [
898
- truncateToWidth(branchStyled, width),
899
- truncateToWidth(repoStyled, width),
900
- truncateToWidth(contextStyled, width),
901
- truncateToWidth(modelStyled, width),
902
- ];
932
+ return renderFooterLines({
933
+ width,
934
+ cwd: ctx.cwd,
935
+ config: state.config,
936
+ branch: footerData.getGitBranch() ?? state.gitCache?.getStatusSnapshot()?.branch ?? "",
937
+ gitStatus: shouldShowGitStatus(state.config)
938
+ ? formatGitFooterStatus(
939
+ state.gitCache?.getStatusSnapshot(),
940
+ state.gitCache?.getPullRequestSnapshot(),
941
+ )
942
+ : undefined,
943
+ contextUsage: ctx.getContextUsage(),
944
+ modelId: ctx.model?.id,
945
+ modelProvider: ctx.model?.provider,
946
+ thinkingLevel: pi.getThinkingLevel(),
947
+ theme,
948
+ usageSnapshot: state.snapshot,
949
+ });
903
950
  },
904
951
  };
905
952
  });
@@ -925,3 +972,16 @@ export default function (pi: ExtensionAPI) {
925
972
  disposeGitCache(state);
926
973
  });
927
974
  }
975
+
976
+ export const __testing = {
977
+ GitFooterCache,
978
+ GIT_STATUS_ARGS,
979
+ GH_PR_VIEW_ARGS,
980
+ loadConfig,
981
+ renderFooterLines,
982
+ parseGitStatusPorcelainV2,
983
+ parsePullRequestJson,
984
+ formatGitStatusFooterSegment,
985
+ formatPullRequestFooterSegment,
986
+ formatGitFooterStatus,
987
+ };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-minimal-footer",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "A minimal custom footer for pi.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-notify",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A pi extension that sends a notification when the agent is ready for input.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-openai-fast",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "A pi extension that enables OpenAI Codex Fast mode for ChatGPT-auth GPT-5.4 and GPT-5.5 by injecting the priority service tier.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3
@@ -82,6 +82,7 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
82
82
  "claude-opus-4-5",
83
83
  "claude-opus-4-1",
84
84
  "claude-opus-4",
85
+ "claude-sonnet-5",
85
86
  "claude-sonnet-4-6",
86
87
  "claude-sonnet-4-5",
87
88
  "claude-sonnet-4",
@@ -106,6 +107,9 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
106
107
  "claude-opus-4.1",
107
108
  "claude-opus-4-0",
108
109
  "claude-opus-4",
110
+ "claude-sonnet-5-0",
111
+ "claude-sonnet-5.0",
112
+ "claude-sonnet-5",
109
113
  "claude-sonnet-4-6",
110
114
  "claude-sonnet-4.6",
111
115
  "claude-sonnet-4-5",
@@ -184,6 +188,8 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
184
188
  "gpt-5",
185
189
  "gemini-3.1-pro-preview",
186
190
  "gemini-3-pro-preview",
191
+ "claude-sonnet-5.0",
192
+ "claude-sonnet-5",
187
193
  "claude-sonnet-4.6",
188
194
  "claude-sonnet-4.5",
189
195
  "gemini-2.5-pro",
@@ -359,6 +365,8 @@ const PROVIDER_MODEL_PREFERENCES: Record<string, string[]> = {
359
365
  "anthropic/claude-opus-4.6",
360
366
  "anthropic/claude-opus-4.5",
361
367
  "anthropic/claude-opus-4.1",
368
+ "anthropic/claude-sonnet-5.0",
369
+ "anthropic/claude-sonnet-5",
362
370
  "anthropic/claude-sonnet-4.6",
363
371
  "openai/gpt-5.5-pro",
364
372
  "openai/gpt-5.5",
@@ -1108,6 +1116,13 @@ function renderCollapsedText(text: string, lineLimit = COLLAPSED_LINE_LIMIT): st
1108
1116
  return [...lines.slice(0, lineLimit), `... (${lines.length - lineLimit} more lines)`].join("\n");
1109
1117
  }
1110
1118
 
1119
+ export const __test__ = {
1120
+ findAvailableModel,
1121
+ parseModelPreference,
1122
+ resolveThinkingLevel,
1123
+ selectOracleModel,
1124
+ };
1125
+
1111
1126
  export default function oracleExtension(pi: ExtensionAPI) {
1112
1127
  const activeRuns = new Map<string, OracleUiRun>();
1113
1128
  let preferences: OraclePreferences = {};
@@ -1270,13 +1285,17 @@ export default function oracleExtension(pi: ExtensionAPI) {
1270
1285
  parameters: OracleParams,
1271
1286
 
1272
1287
  async execute(toolCallId, params, signal, onUpdate, ctx) {
1288
+ const rawTask = (params as { task?: unknown }).task;
1289
+ const task = typeof rawTask === "string" ? rawTask.trim() : "";
1290
+ if (!task) throw new Error("Invalid parameters: expected task to be a non-empty string.");
1291
+
1273
1292
  const explicitModel = parseModelPreference(params.model);
1274
1293
  const defaultModel = parseModelPreference(preferences.model);
1275
1294
  const configuredModel = explicitModel.model ?? defaultModel.model;
1276
1295
  const configuredThinkingLevel =
1277
1296
  params.thinkingLevel ?? explicitModel.thinkingLevel ?? preferences.thinkingLevel ?? defaultModel.thinkingLevel;
1278
1297
  const uiRun: OracleUiRun = {
1279
- task: params.task,
1298
+ task,
1280
1299
  includeBash: params.includeBash ?? false,
1281
1300
  startedAt: Date.now(),
1282
1301
  };
@@ -1368,7 +1387,7 @@ export default function oracleExtension(pi: ExtensionAPI) {
1368
1387
  uiRun.selection = attempt;
1369
1388
  updateOracleUi(ctx, activeRuns);
1370
1389
 
1371
- const result = await runOracle(attempt, params, signal, handleUpdate, ctx.cwd);
1390
+ const result = await runOracle(attempt, { ...params, task }, signal, handleUpdate, ctx.cwd);
1372
1391
  if (result.ok) {
1373
1392
  return {
1374
1393
  content: [{ type: "text", text: result.output }],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-oracle",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "An Amp-style oracle extension for pi that consults the strongest reasoning model on your current provider.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3
@@ -13,7 +13,11 @@ export default function (pi: ExtensionAPI) {
13
13
  pi.on("tool_call", async (event, ctx) => {
14
14
  if (event.toolName !== "bash") return undefined;
15
15
 
16
- const command = event.input.command as string;
16
+ const command = event.input?.command;
17
+ if (typeof command !== "string" || command.trim() === "") {
18
+ return { block: true, reason: "Malformed bash command blocked" };
19
+ }
20
+
17
21
  const isDangerous = dangerousPatterns.some((p) => p.test(command));
18
22
 
19
23
  if (isDangerous) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-permission-gate",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "A pi extension that prompts before dangerous bash commands.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3
@@ -307,6 +307,12 @@ function createQuietToolDefinitions(cwd: string, enabled: boolean): ToolDefiniti
307
307
  return enabled ? baseDefinitions.map(createQuietToolDefinition) : baseDefinitions;
308
308
  }
309
309
 
310
+ export const __testing = {
311
+ sanitizeInlineText,
312
+ formatQuietCallLine,
313
+ createQuietToolDefinition,
314
+ };
315
+
310
316
  export default function quietToolsExtension(pi: ExtensionAPI) {
311
317
  let enabled = true;
312
318
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegopetrucci/pi-quiet-tools",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "A pi extension that visually compacts collapsed built-in tool rows in the TUI without changing tool results sent to the model.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1 +1 @@
1
- 0.79.10
1
+ 0.80.3