pi-harness-runtime 0.9.5 → 0.9.7
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 +29 -0
- package/index.ts +93 -6
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/proactive-compact.ts +28 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.9.7](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.5...v0.9.7) (2026-07-16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* harden auto-resume after compaction ([13378e8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/13378e852c984ead0e66f0adeffc073ff58af50c))
|
|
11
|
+
* resume after output-limit error stops ([8c75a24](https://github.com/ManotLuijiu/pi-harness-runtime/commit/8c75a2432082c4f9ba6296ffe2d04b636863bf2f))
|
|
12
|
+
|
|
13
|
+
### [0.9.3](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.3) (2026-07-14)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* auto-resume pi dev with literal resume ([#51](https://github.com/ManotLuijiu/pi-harness-runtime/issues/51)) ([fd98762](https://github.com/ManotLuijiu/pi-harness-runtime/commit/fd987629f6062a4a7ff7a28d9dfb607962f5a4a9))
|
|
19
|
+
|
|
20
|
+
### [0.9.6](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.5...v0.9.6) (2026-07-16)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* harden auto-resume after compaction ([13378e8](https://github.com/ManotLuijiu/pi-harness-runtime/commit/13378e852c984ead0e66f0adeffc073ff58af50c))
|
|
26
|
+
|
|
27
|
+
### [0.9.3](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.5.0-beta.1...v0.9.3) (2026-07-14)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Bug Fixes
|
|
31
|
+
|
|
32
|
+
* auto-resume pi dev with literal resume ([#51](https://github.com/ManotLuijiu/pi-harness-runtime/issues/51)) ([fd98762](https://github.com/ManotLuijiu/pi-harness-runtime/commit/fd987629f6062a4a7ff7a28d9dfb607962f5a4a9))
|
|
33
|
+
|
|
5
34
|
### [0.9.5](https://github.com/ManotLuijiu/pi-harness-runtime/compare/v0.9.4...v0.9.5) (2026-07-15)
|
|
6
35
|
|
|
7
36
|
|
package/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { MiniMaxQuotaScraper } from "./harness/e2e/minimax-quota-scraper.js";
|
|
|
25
25
|
import { parseMiniMaxQuotaText } from "./harness/e2e/minimax-quota-parser.js";
|
|
26
26
|
import { buildFooterStatusValue } from "./footer-status.ts";
|
|
27
27
|
import {
|
|
28
|
+
MAX_PROACTIVE_COMPACT_FAILURES,
|
|
28
29
|
OUTPUT_LIMIT_RESUME_PROMPT,
|
|
29
30
|
PROACTIVE_COMPACT_COOLDOWN_MS,
|
|
30
31
|
shouldQueueOutputLimitResume,
|
|
@@ -80,6 +81,33 @@ async function getCheckpointManager(): Promise<CheckpointManager> {
|
|
|
80
81
|
) as unknown as CheckpointManager;
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
function isOutputLimitResumePromptMessage(message: {
|
|
85
|
+
role?: string;
|
|
86
|
+
content?: unknown;
|
|
87
|
+
}): boolean {
|
|
88
|
+
if (message.role !== "user") {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (typeof message.content === "string") {
|
|
92
|
+
return message.content === OUTPUT_LIMIT_RESUME_PROMPT;
|
|
93
|
+
}
|
|
94
|
+
if (!Array.isArray(message.content)) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return (
|
|
98
|
+
message.content
|
|
99
|
+
.filter(
|
|
100
|
+
(part): part is { type: "text"; text: string } =>
|
|
101
|
+
part &&
|
|
102
|
+
typeof part === "object" &&
|
|
103
|
+
(part as { type?: unknown }).type === "text" &&
|
|
104
|
+
typeof (part as { text?: unknown }).text === "string",
|
|
105
|
+
)
|
|
106
|
+
.map((part) => part.text)
|
|
107
|
+
.join("\n") === OUTPUT_LIMIT_RESUME_PROMPT
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
83
111
|
export default function (pi: ExtensionAPI) {
|
|
84
112
|
const tracker = new UsageTracker();
|
|
85
113
|
const mirrorStore = new MirrorStore();
|
|
@@ -87,6 +115,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
87
115
|
|
|
88
116
|
// ─── Auto-track every assistant message ──────────────────────────────
|
|
89
117
|
pi.on("message_end", async (event, ctx) => {
|
|
118
|
+
if (isOutputLimitResumePromptMessage(event.message)) {
|
|
119
|
+
pendingOutputLimitResumeAfterSettled = false;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
90
122
|
if (event.message.role !== "assistant") return;
|
|
91
123
|
const m = event.message as {
|
|
92
124
|
role?: string;
|
|
@@ -109,9 +141,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
109
141
|
)
|
|
110
142
|
) {
|
|
111
143
|
outputLimitResumeAttempts += 1;
|
|
112
|
-
|
|
144
|
+
pendingOutputLimitResumeAfterCompact = true;
|
|
145
|
+
pendingOutputLimitResumeAfterSettled = true;
|
|
146
|
+
queueAutoResume("output-limit", OUTPUT_LIMIT_RESUME_PROMPT, "steer");
|
|
113
147
|
} else if (m.stopReason === "stop") {
|
|
114
148
|
outputLimitResumeAttempts = 0;
|
|
149
|
+
pendingOutputLimitResumeAfterSettled = false;
|
|
115
150
|
}
|
|
116
151
|
|
|
117
152
|
if (!m.usage) return;
|
|
@@ -141,7 +176,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
141
176
|
let quotaAutoFetchInFlight = false;
|
|
142
177
|
let proactiveCompactInFlight = false;
|
|
143
178
|
let lastProactiveCompactAt = 0;
|
|
179
|
+
let consecutiveCompactFailures = 0;
|
|
180
|
+
let proactiveCompactCircuitReported = false;
|
|
144
181
|
let outputLimitResumeAttempts = 0;
|
|
182
|
+
let pendingOutputLimitResumeAfterCompact = false;
|
|
183
|
+
let pendingOutputLimitResumeAfterSettled = false;
|
|
145
184
|
|
|
146
185
|
function writeMirrorRecord(record: MirrorRecord): void {
|
|
147
186
|
mirrorStore.write(record);
|
|
@@ -678,24 +717,60 @@ export default function (pi: ExtensionAPI) {
|
|
|
678
717
|
maybeTriggerProactiveCompact(ctx);
|
|
679
718
|
});
|
|
680
719
|
|
|
720
|
+
pi.on("agent_end", () => {
|
|
721
|
+
setTimeout(() => {
|
|
722
|
+
if (!pendingOutputLimitResumeAfterSettled) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
pendingOutputLimitResumeAfterSettled = false;
|
|
726
|
+
queueAutoResume(
|
|
727
|
+
"output-limit-settled",
|
|
728
|
+
OUTPUT_LIMIT_RESUME_PROMPT,
|
|
729
|
+
"followUp",
|
|
730
|
+
);
|
|
731
|
+
}, 0);
|
|
732
|
+
});
|
|
733
|
+
|
|
681
734
|
pi.on("session_compact", (event, ctx) => {
|
|
682
735
|
footerStatusCtx = ctx;
|
|
683
736
|
proactiveCompactInFlight = false;
|
|
684
737
|
lastProactiveCompactAt = Date.now();
|
|
685
|
-
|
|
738
|
+
consecutiveCompactFailures = 0;
|
|
739
|
+
proactiveCompactCircuitReported = false;
|
|
686
740
|
refreshFooterStatus(ctx, tracker, mirrorStore);
|
|
687
741
|
|
|
688
|
-
|
|
742
|
+
const forceOutputLimitResume = pendingOutputLimitResumeAfterCompact;
|
|
743
|
+
pendingOutputLimitResumeAfterCompact = false;
|
|
744
|
+
|
|
745
|
+
if (
|
|
746
|
+
!shouldQueuePostCompactionResume(event, ctx.hasPendingMessages(), {
|
|
747
|
+
force: forceOutputLimitResume,
|
|
748
|
+
})
|
|
749
|
+
) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (forceOutputLimitResume) {
|
|
754
|
+
queueAutoResume(
|
|
755
|
+
"post-compact-output-limit",
|
|
756
|
+
OUTPUT_LIMIT_RESUME_PROMPT,
|
|
757
|
+
event.willRetry ? "steer" : "followUp",
|
|
758
|
+
);
|
|
689
759
|
return;
|
|
690
760
|
}
|
|
691
761
|
|
|
762
|
+
outputLimitResumeAttempts = 0;
|
|
692
763
|
// pi.dev expects the literal "resume" command to continue after compaction.
|
|
693
|
-
queueAutoResume("post-compact", "resume");
|
|
764
|
+
queueAutoResume("post-compact", "resume", "followUp");
|
|
694
765
|
});
|
|
695
766
|
|
|
696
|
-
function queueAutoResume(
|
|
767
|
+
function queueAutoResume(
|
|
768
|
+
reason: string,
|
|
769
|
+
content: string,
|
|
770
|
+
deliverAs: "steer" | "followUp",
|
|
771
|
+
): void {
|
|
697
772
|
try {
|
|
698
|
-
pi.sendUserMessage(content, { deliverAs
|
|
773
|
+
pi.sendUserMessage(content, { deliverAs });
|
|
699
774
|
} catch (error) {
|
|
700
775
|
console.error(
|
|
701
776
|
`[pi-harness] Failed to queue ${reason} auto-resume:`,
|
|
@@ -708,6 +783,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
708
783
|
if (proactiveCompactInFlight) {
|
|
709
784
|
return;
|
|
710
785
|
}
|
|
786
|
+
if (consecutiveCompactFailures >= MAX_PROACTIVE_COMPACT_FAILURES) {
|
|
787
|
+
if (!proactiveCompactCircuitReported) {
|
|
788
|
+
proactiveCompactCircuitReported = true;
|
|
789
|
+
console.error(
|
|
790
|
+
`[pi-harness] Proactive compact disabled after ${consecutiveCompactFailures} consecutive failures`,
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
711
795
|
if (!ctx.isIdle() || ctx.hasPendingMessages()) {
|
|
712
796
|
return;
|
|
713
797
|
}
|
|
@@ -728,9 +812,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
728
812
|
onComplete: () => {
|
|
729
813
|
proactiveCompactInFlight = false;
|
|
730
814
|
lastProactiveCompactAt = Date.now();
|
|
815
|
+
consecutiveCompactFailures = 0;
|
|
816
|
+
proactiveCompactCircuitReported = false;
|
|
731
817
|
},
|
|
732
818
|
onError: (error) => {
|
|
733
819
|
proactiveCompactInFlight = false;
|
|
820
|
+
consecutiveCompactFailures += 1;
|
|
734
821
|
console.error("[pi-harness] Proactive compact failed:", error.message);
|
|
735
822
|
},
|
|
736
823
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/provider-router",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"description": "Enhanced Provider Router for pi-harness-runtime — intelligent routing with capabilities, costs, and quotas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/provider-router.js",
|
package/proactive-compact.ts
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import type { ContextUsage } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
export const PROACTIVE_COMPACT_THRESHOLD = 0.9;
|
|
4
|
+
export const PROACTIVE_COMPACT_HEADROOM_TOKENS = 15_000;
|
|
4
5
|
export const PROACTIVE_COMPACT_COOLDOWN_MS = 10 * 60 * 1000;
|
|
6
|
+
export const MAX_PROACTIVE_COMPACT_FAILURES = 3;
|
|
5
7
|
export const OUTPUT_LIMIT_AUTO_RESUME_LIMIT = 3;
|
|
6
8
|
export const OUTPUT_LIMIT_RESUME_PROMPT =
|
|
7
9
|
"Output token limit hit. Resume directly — no apology, no recap. Pick up mid-thought if the cut happened there. Break remaining work into smaller pieces.";
|
|
8
10
|
|
|
9
11
|
export function shouldTriggerProactiveCompact(
|
|
10
12
|
usage: ContextUsage | undefined,
|
|
11
|
-
options?: { threshold?: number },
|
|
13
|
+
options?: { threshold?: number; headroomTokens?: number },
|
|
12
14
|
): boolean {
|
|
13
|
-
|
|
14
|
-
if (!usage || usage.percent === null) {
|
|
15
|
+
if (!usage) {
|
|
15
16
|
return false;
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
const headroomTokens =
|
|
20
|
+
options?.headroomTokens ?? PROACTIVE_COMPACT_HEADROOM_TOKENS;
|
|
21
|
+
if (
|
|
22
|
+
usage.tokens !== null &&
|
|
23
|
+
usage.contextWindow - usage.tokens <= headroomTokens
|
|
24
|
+
) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const threshold = options?.threshold ?? PROACTIVE_COMPACT_THRESHOLD;
|
|
29
|
+
return usage.percent !== null && usage.percent >= threshold;
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
export type AssistantStopLike = {
|
|
@@ -61,8 +73,18 @@ export function shouldQueueOutputLimitResume(
|
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
export function shouldQueuePostCompactionResume(
|
|
64
|
-
event: {
|
|
76
|
+
event: {
|
|
77
|
+
willRetry?: boolean;
|
|
78
|
+
reason?: "manual" | "threshold" | "overflow" | string;
|
|
79
|
+
},
|
|
65
80
|
hasPendingMessages: boolean,
|
|
81
|
+
options?: { force?: boolean },
|
|
66
82
|
): boolean {
|
|
67
|
-
|
|
83
|
+
if (event.reason === "manual" && options?.force !== true) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
(options?.force === true || event.willRetry !== true) && !hasPendingMessages
|
|
89
|
+
);
|
|
68
90
|
}
|