pi-bar 0.3.19 → 0.3.21
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/README.md +1 -1
- package/extensions/status-footer.ts +76 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
claude-opus-4.7 ❯ think:med ❯ 2.6% / 1.0M ❯ Inspecting package structure ❯ plan:active
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-

|
|
13
13
|
|
|
14
14
|
## Why use it?
|
|
15
15
|
|
|
@@ -53,6 +53,7 @@ type TldrActivity = {
|
|
|
53
53
|
activityType: TldrActivityType;
|
|
54
54
|
displayPriority: TldrDisplayPriority;
|
|
55
55
|
text: string;
|
|
56
|
+
toolCallId?: string;
|
|
56
57
|
};
|
|
57
58
|
type TldrCheckpoint = {
|
|
58
59
|
activityIndex: number;
|
|
@@ -365,12 +366,18 @@ function usefulLineCount(text: string): number {
|
|
|
365
366
|
.filter(Boolean).length;
|
|
366
367
|
}
|
|
367
368
|
|
|
369
|
+
const ERROR_LINE_PATTERN = /(error|failed|TS\d+|E[A-Z]+\d*|Command exited|denied|refused|aborted|panic|fatal|exception)/i;
|
|
370
|
+
|
|
368
371
|
function errorSummary(text: string | undefined): string | undefined {
|
|
369
372
|
if (!text) return undefined;
|
|
370
|
-
const
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
const cleaned = text.replace(ANSI_PATTERN, "");
|
|
374
|
+
const lines = cleaned
|
|
375
|
+
.split("\n")
|
|
376
|
+
.map((line) => line.trim())
|
|
377
|
+
.filter(Boolean);
|
|
378
|
+
if (lines.length === 0) return undefined;
|
|
379
|
+
const matched = lines.find((line) => ERROR_LINE_PATTERN.test(line)) ?? lines[lines.length - 1];
|
|
380
|
+
return truncateText(compactText(matched), MAX_TOOL_RESULT_ERROR_CHARS);
|
|
374
381
|
}
|
|
375
382
|
|
|
376
383
|
function summarizeToolResult(
|
|
@@ -442,20 +449,32 @@ class TldrFactCollector {
|
|
|
442
449
|
const record = message as Record<string, unknown>;
|
|
443
450
|
if (record.role !== "assistant") return undefined;
|
|
444
451
|
const text = extractTextContent(record.content as readonly unknown[] | undefined);
|
|
445
|
-
return
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
+
if (!text) return undefined;
|
|
453
|
+
|
|
454
|
+
// Streaming emits many partial updates per message. Keep only the latest by
|
|
455
|
+
// dropping the previous assistant_update so the model sees one accurate snapshot.
|
|
456
|
+
const last = this.activities[this.activities.length - 1];
|
|
457
|
+
if (last?.activityType === "assistant_update") {
|
|
458
|
+
this.activities.pop();
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return this.addActivity(
|
|
462
|
+
"assistant_update",
|
|
463
|
+
"normal",
|
|
464
|
+
`assistant: ${tailText(text, MAX_ASSISTANT_UPDATE_CHARS)}`,
|
|
465
|
+
);
|
|
452
466
|
}
|
|
453
467
|
|
|
454
|
-
recordToolCall(event: {
|
|
468
|
+
recordToolCall(event: {
|
|
469
|
+
toolName: string;
|
|
470
|
+
input?: Record<string, unknown>;
|
|
471
|
+
toolCallId?: string;
|
|
472
|
+
}): TldrActivity {
|
|
455
473
|
return this.addActivity(
|
|
456
474
|
"tool_call",
|
|
457
475
|
"normal",
|
|
458
476
|
`tool: ${compactToolInput(event.toolName, event.input)}`,
|
|
477
|
+
event.toolCallId,
|
|
459
478
|
);
|
|
460
479
|
}
|
|
461
480
|
|
|
@@ -465,6 +484,7 @@ class TldrFactCollector {
|
|
|
465
484
|
isError?: boolean;
|
|
466
485
|
content?: readonly unknown[];
|
|
467
486
|
details?: unknown;
|
|
487
|
+
toolCallId?: string;
|
|
468
488
|
}): TldrActivity {
|
|
469
489
|
const isError = Boolean(event.isError);
|
|
470
490
|
const resultText = summarizeToolResult(
|
|
@@ -475,12 +495,25 @@ class TldrFactCollector {
|
|
|
475
495
|
);
|
|
476
496
|
const status = isError ? "error" : "ok";
|
|
477
497
|
const tool = compactToolInput(event.toolName, event.input);
|
|
498
|
+
|
|
499
|
+
// Result fact subsumes the prior tool_call fact for the same call. Drop the
|
|
500
|
+
// matching tool_call so the model sees one combined fact instead of two.
|
|
501
|
+
if (event.toolCallId) {
|
|
502
|
+
const idx = this.activities.findIndex(
|
|
503
|
+
(activity) =>
|
|
504
|
+
activity.activityType === "tool_call" &&
|
|
505
|
+
activity.toolCallId === event.toolCallId,
|
|
506
|
+
);
|
|
507
|
+
if (idx !== -1) this.activities.splice(idx, 1);
|
|
508
|
+
}
|
|
509
|
+
|
|
478
510
|
return this.addActivity(
|
|
479
511
|
"tool_result",
|
|
480
512
|
"normal",
|
|
481
513
|
resultText
|
|
482
514
|
? `result: ${tool} ${status}; ${resultText}`
|
|
483
515
|
: `result: ${tool} ${status}`,
|
|
516
|
+
event.toolCallId,
|
|
484
517
|
);
|
|
485
518
|
}
|
|
486
519
|
|
|
@@ -538,12 +571,14 @@ class TldrFactCollector {
|
|
|
538
571
|
activityType: TldrActivityType,
|
|
539
572
|
displayPriority: TldrDisplayPriority,
|
|
540
573
|
text: string,
|
|
574
|
+
toolCallId?: string,
|
|
541
575
|
): TldrActivity {
|
|
542
576
|
const activity = {
|
|
543
577
|
index: this.nextIndex,
|
|
544
578
|
activityType,
|
|
545
579
|
displayPriority,
|
|
546
580
|
text: truncateText(text, MAX_ACTIVITY_TEXT_CHARS),
|
|
581
|
+
toolCallId,
|
|
547
582
|
};
|
|
548
583
|
this.nextIndex++;
|
|
549
584
|
this.activities.push(activity);
|
|
@@ -600,7 +635,7 @@ class FooterTldrEngine {
|
|
|
600
635
|
|
|
601
636
|
recordToolCall(
|
|
602
637
|
ctx: ExtensionContext,
|
|
603
|
-
event: { toolName: string; input?: Record<string, unknown
|
|
638
|
+
event: { toolName: string; input?: Record<string, unknown>; toolCallId?: string },
|
|
604
639
|
): void {
|
|
605
640
|
this.enqueue(ctx, this.facts.recordToolCall(event));
|
|
606
641
|
}
|
|
@@ -613,6 +648,7 @@ class FooterTldrEngine {
|
|
|
613
648
|
isError?: boolean;
|
|
614
649
|
content?: readonly unknown[];
|
|
615
650
|
details?: unknown;
|
|
651
|
+
toolCallId?: string;
|
|
616
652
|
},
|
|
617
653
|
): void {
|
|
618
654
|
this.enqueue(ctx, this.facts.recordToolResult(event));
|
|
@@ -741,7 +777,8 @@ class FooterTldrEngine {
|
|
|
741
777
|
);
|
|
742
778
|
if (!this.isCurrentJob(job) || response.stopReason !== "stop") return;
|
|
743
779
|
|
|
744
|
-
const
|
|
780
|
+
const rawText = extractTextContent(response.content) ?? "";
|
|
781
|
+
const text = sanitizeTldrText(rawText);
|
|
745
782
|
if (!text) return;
|
|
746
783
|
const checkpoint = {
|
|
747
784
|
activityIndex: job.activityIndex,
|
|
@@ -826,13 +863,13 @@ class FooterTldrEngine {
|
|
|
826
863
|
{
|
|
827
864
|
type: "text",
|
|
828
865
|
text: [
|
|
829
|
-
"
|
|
866
|
+
"Prior TLDRs (context only, do not copy phrasing):",
|
|
830
867
|
previousCheckpointLines(this.acceptedCheckpoints),
|
|
831
868
|
"",
|
|
832
|
-
"New
|
|
869
|
+
"New activity to summarize:",
|
|
833
870
|
...rawActivities.map(formatRawActivity),
|
|
834
871
|
"",
|
|
835
|
-
|
|
872
|
+
"Write the next TLDR.",
|
|
836
873
|
].join("\n"),
|
|
837
874
|
},
|
|
838
875
|
],
|
|
@@ -848,14 +885,16 @@ function checkpointSystemPrompt(job: TldrCheckpointJob): string {
|
|
|
848
885
|
: "Start with a present-tense -ing verb.";
|
|
849
886
|
return `Write one plain-English TLDR for a terminal coding agent.
|
|
850
887
|
Use the prior TLDRs for context and the new activity for the update.
|
|
851
|
-
Summarize
|
|
888
|
+
Summarize the current state of work; do not narrate the history.
|
|
852
889
|
If context is sparse, still summarize the available activity.
|
|
853
890
|
Never ask for more information or say there is not enough context.
|
|
854
891
|
Return one concise status fragment under ${TLDR_TARGET_SUMMARY_CHARS} characters.
|
|
855
892
|
Omit subjects like "the agent" or "it".
|
|
856
893
|
Prefer verb + direct object. Include outcome only if important.
|
|
857
894
|
Do not address the user.
|
|
858
|
-
|
|
895
|
+
Do not mention activity numbers, indexes, checkpoints, prior TLDRs, or phrases like "through activity".
|
|
896
|
+
Output only the status fragment itself. No prefixes, labels, bullets, or quotes.
|
|
897
|
+
Plain text only; no markdown, JSON, code, file paths, or tool names.
|
|
859
898
|
${tenseInstruction}`;
|
|
860
899
|
}
|
|
861
900
|
|
|
@@ -863,12 +902,28 @@ function previousCheckpointLines(checkpoints: readonly TldrCheckpoint[]): string
|
|
|
863
902
|
if (checkpoints.length === 0) return "none";
|
|
864
903
|
return checkpoints
|
|
865
904
|
.slice(-MAX_CONTEXT_CHECKPOINTS)
|
|
866
|
-
.map((checkpoint) => `-
|
|
905
|
+
.map((checkpoint) => `- ${sanitizeTldrText(checkpoint.text)}`)
|
|
867
906
|
.join("\n");
|
|
868
907
|
}
|
|
869
908
|
|
|
870
909
|
function formatRawActivity(activity: TldrActivity): string {
|
|
871
|
-
return
|
|
910
|
+
return `- ${activity.text}`;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
const LEAKED_PREFIX_PATTERN =
|
|
914
|
+
/^\s*(?:[-*•]\s*)?(?:(?:through\s+activity|activity|checkpoint|tldr|summary)\s*[#:\-—–]?\s*\d*[:\.\-—–]?\s*)+/i;
|
|
915
|
+
|
|
916
|
+
const LEADING_PUNCT_PATTERN = /^[\s\-—–•*:#.,;]+/;
|
|
917
|
+
|
|
918
|
+
function sanitizeTldrText(text: string): string {
|
|
919
|
+
let cleaned = text.trim();
|
|
920
|
+
let previous: string;
|
|
921
|
+
do {
|
|
922
|
+
previous = cleaned;
|
|
923
|
+
cleaned = cleaned.replace(LEAKED_PREFIX_PATTERN, "").trim();
|
|
924
|
+
cleaned = cleaned.replace(LEADING_PUNCT_PATTERN, "").trim();
|
|
925
|
+
} while (cleaned !== previous && cleaned.length > 0);
|
|
926
|
+
return cleaned || text.trim();
|
|
872
927
|
}
|
|
873
928
|
|
|
874
929
|
function shouldShowStatus(key: string, filter: StatusFilter): boolean {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-bar",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.21",
|
|
4
4
|
"description": "Pi footer/statusline showing active model, thinking level, context pressure, live TLDR, and extension statuses.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -51,6 +51,6 @@
|
|
|
51
51
|
"extensions": [
|
|
52
52
|
"./extensions/status-footer.ts"
|
|
53
53
|
],
|
|
54
|
-
"image": "https://cdn.jsdelivr.net/npm/pi-bar@0.3.
|
|
54
|
+
"image": "https://cdn.jsdelivr.net/npm/pi-bar@0.3.21/assets/screenshot.png"
|
|
55
55
|
}
|
|
56
56
|
}
|