pi-harness-runtime 1.1.30 → 1.1.32

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 (104) hide show
  1. package/harness/langchain/agents.ts +198 -0
  2. package/harness/langchain/checkpointer.test.ts +269 -0
  3. package/harness/langchain/checkpointer.ts +343 -0
  4. package/harness/langchain/daemon.test.ts +398 -0
  5. package/harness/langchain/daemon.ts +921 -0
  6. package/harness/langchain/graph.ts +291 -0
  7. package/harness/langchain/models.ts +95 -0
  8. package/harness/langchain/run.ts +207 -0
  9. package/harness/langchain/surge.test.ts +214 -0
  10. package/harness/langchain/surge.ts +217 -0
  11. package/package.json +8 -2
  12. package/packages/a2a-adapter/package.json +1 -1
  13. package/packages/architecture-generator/package.json +1 -1
  14. package/packages/auth/package.json +1 -1
  15. package/packages/autonomous-refactor/package.json +1 -1
  16. package/packages/autonomous-runtime/package.json +1 -1
  17. package/packages/cache-strategy/package.json +1 -1
  18. package/packages/capability-registry/package.json +1 -1
  19. package/packages/checkpoint/package.json +1 -1
  20. package/packages/cli-plugin-sdk/package.json +1 -1
  21. package/packages/clipboard/package.json +1 -1
  22. package/packages/clipboard-plugin/package.json +1 -1
  23. package/packages/code-generation/package.json +1 -1
  24. package/packages/code-review/package.json +1 -1
  25. package/packages/codex-adapter/package.json +1 -1
  26. package/packages/config-capture/package.json +1 -1
  27. package/packages/context-compiler/package.json +1 -1
  28. package/packages/context-discovery/package.json +1 -1
  29. package/packages/context-manager/package.json +1 -1
  30. package/packages/cookie-sanitizer/package.json +1 -1
  31. package/packages/cost-optimizer/package.json +1 -1
  32. package/packages/dependency-analyzer/package.json +1 -1
  33. package/packages/django-plugin/package.json +1 -1
  34. package/packages/doc-generator/package.json +1 -1
  35. package/packages/evaluation-engine/package.json +1 -1
  36. package/packages/evaluation-runner/package.json +1 -1
  37. package/packages/event-bus/dist/src/types.d.ts +1 -1
  38. package/packages/event-bus/dist/src/types.d.ts.map +1 -1
  39. package/packages/event-bus/dist/src/types.js.map +1 -1
  40. package/packages/event-bus/package.json +1 -1
  41. package/packages/event-bus/src/types.ts +1 -0
  42. package/packages/event-store/package.json +1 -1
  43. package/packages/experience-replay/package.json +1 -1
  44. package/packages/feedback-collector/package.json +1 -1
  45. package/packages/file-copy-helper/package.json +1 -1
  46. package/packages/framework-detector/package.json +1 -1
  47. package/packages/framework-plugin-sdk/package.json +1 -1
  48. package/packages/frappe-plugin/package.json +1 -1
  49. package/packages/generic-web-plugin/package.json +1 -1
  50. package/packages/health-monitor/package.json +1 -1
  51. package/packages/intent-analyzer/package.json +1 -1
  52. package/packages/knowledge-graph/package.json +1 -1
  53. package/packages/knowledge-retrieval/package.json +1 -1
  54. package/packages/laravel-plugin/package.json +1 -1
  55. package/packages/learning-engine/package.json +1 -1
  56. package/packages/mcp-adapter/package.json +1 -1
  57. package/packages/memory-engine/package.json +1 -1
  58. package/packages/milestone-manager/package.json +1 -1
  59. package/packages/model-registry/package.json +1 -1
  60. package/packages/nextjs-plugin/package.json +1 -1
  61. package/packages/notification/package.json +1 -1
  62. package/packages/observability/package.json +1 -1
  63. package/packages/okf-indexer/package.json +1 -1
  64. package/packages/performance-optimizer/package.json +1 -1
  65. package/packages/privilege-broker/package.json +1 -1
  66. package/packages/project-analyzer/package.json +1 -1
  67. package/packages/project-bootstrap/package.json +1 -1
  68. package/packages/projection-engine/package.json +1 -1
  69. package/packages/prompt-compiler/package.json +1 -1
  70. package/packages/prompt-versioning/package.json +1 -1
  71. package/packages/provider-adapter-sdk/package.json +1 -1
  72. package/packages/provider-router/package.json +1 -1
  73. package/packages/provider-selector/package.json +1 -1
  74. package/packages/providers/package.json +1 -1
  75. package/packages/quota-manager/package.json +1 -1
  76. package/packages/rate-limiter/package.json +1 -1
  77. package/packages/react-vite-plugin/package.json +1 -1
  78. package/packages/release-manager/package.json +1 -1
  79. package/packages/requirement-compiler/package.json +1 -1
  80. package/packages/runtime/package.json +1 -1
  81. package/packages/scheduler/package.json +1 -1
  82. package/packages/scheduler-adapter/package.json +1 -1
  83. package/packages/session/package.json +1 -1
  84. package/packages/session-api/package.json +1 -1
  85. package/packages/session-export/package.json +1 -1
  86. package/packages/shared-context/package.json +1 -1
  87. package/packages/skill-mcp-client/package.json +1 -1
  88. package/packages/skill-registry/package.json +1 -1
  89. package/packages/sprint-planner/package.json +1 -1
  90. package/packages/subscription-engine/package.json +1 -1
  91. package/packages/task-compiler/package.json +1 -1
  92. package/packages/tencentdb-memory/package.json +1 -1
  93. package/packages/tencentdb-sync/package.json +1 -1
  94. package/packages/test-data-generator/package.json +1 -1
  95. package/packages/test-generator/package.json +1 -1
  96. package/packages/todo-bd-sync/package.json +1 -1
  97. package/packages/token-estimation/package.json +1 -1
  98. package/packages/token-optimizer/package.json +1 -1
  99. package/packages/tui/package.json +1 -1
  100. package/packages/types/package.json +1 -1
  101. package/packages/workflow-events/package.json +1 -1
  102. package/packages/workspace-scanner/package.json +1 -1
  103. package/packages/worktree/package.json +1 -1
  104. package/packages/write-review/package.json +1 -1
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Surge auto-resume tests — S2/S4 acceptance (wiki/peak-hour-surge-auto-resume.md)
3
+ *
4
+ * All deterministic via injected sleep/rand — no real timers, no API keys.
5
+ *
6
+ * Run:
7
+ * bun test harness/langchain/surge.test.ts
8
+ */
9
+
10
+ import { describe, it } from "node:test";
11
+ import assert from "node:assert";
12
+
13
+ import {
14
+ classifySurge,
15
+ computeSurgeDelayMs,
16
+ invokeWithSurgeRetry,
17
+ SurgeScheduler,
18
+ type SurgePolicy,
19
+ } from "./surge.js";
20
+ import type { LoopDeps } from "./graph.js";
21
+
22
+ // ─── Fixtures ────────────────────────────────────────────────────────────────
23
+
24
+ /** The exact incident message from the amos-saas E2E failure (2026-08-31). */
25
+ const INCIDENT =
26
+ '529 {"type":"error","error":{"type":"overloaded_error","message":"The system is currently experiencing a peak-hour surge, and the server is temporarily busy. It usually recovers within 1–5 minutes. Please try again shortly (2064)"},"request_id":"06e405e2e5965672576925264941a057"}';
27
+
28
+ const SIGNAL_3MIN = {
29
+ retryAfterMs: 180_000,
30
+ explicit: true,
31
+ sourceText: INCIDENT,
32
+ };
33
+
34
+ const FAST_POLICY: Partial<SurgePolicy> = {
35
+ baseDelayMs: 100,
36
+ multiplier: 2,
37
+ minDelayMs: 10,
38
+ maxDelayMs: 1_000,
39
+ jitterRatio: 0,
40
+ maxAttempts: 3,
41
+ };
42
+
43
+ // ─── T1 Classification ───────────────────────────────────────────────────────
44
+
45
+ describe("T1 — classifySurge", () => {
46
+ it("classifies the incident message (midpoint of 1–5 min = 3 min)", () => {
47
+ const sig = classifySurge(new Error(INCIDENT));
48
+ assert.ok(sig, "should classify");
49
+ assert.equal(sig?.retryAfterMs, 180_000);
50
+ assert.equal(sig?.explicit, true);
51
+ });
52
+
53
+ it("classifies plain 529 status", () => {
54
+ const sig = classifySurge(new Error("HTTP 529"));
55
+ assert.ok(sig);
56
+ assert.equal(sig?.explicit, false); // no stated delay → 2 min default
57
+ assert.equal(sig?.retryAfterMs, 120_000);
58
+ });
59
+
60
+ it("parses 'retry after 30 seconds'", () => {
61
+ const sig = classifySurge(
62
+ new Error("overloaded — please retry after 30 seconds"),
63
+ );
64
+ assert.ok(sig);
65
+ assert.equal(sig?.retryAfterMs, 30_000);
66
+ });
67
+
68
+ it("parses retry-after milliseconds", () => {
69
+ const sig = classifySurge(new Error("529; retry-after: 45000ms"));
70
+ assert.ok(sig);
71
+ assert.equal(sig?.retryAfterMs, 45_000);
72
+ });
73
+
74
+ it("rejects non-surge errors", () => {
75
+ assert.equal(classifySurge(new Error("429 too many requests")), null);
76
+ assert.equal(classifySurge(new Error("ECONNREFUSED")), null);
77
+ assert.equal(classifySurge("file not found"), null);
78
+ });
79
+ });
80
+
81
+ // ─── T2/T3 Delay computation & escalation ────────────────────────────────────
82
+
83
+ describe("T2 — computeSurgeDelayMs escalation", () => {
84
+ it("escalates 3 → 6 → 12 min and caps at max", () => {
85
+ const p = { jitterRatio: 0 } as const; // deterministic
86
+ assert.equal(computeSurgeDelayMs(SIGNAL_3MIN, 1, p), 180_000);
87
+ assert.equal(computeSurgeDelayMs(SIGNAL_3MIN, 2, p), 360_000);
88
+ assert.equal(computeSurgeDelayMs(SIGNAL_3MIN, 3, p), 720_000);
89
+ assert.equal(computeSurgeDelayMs(SIGNAL_3MIN, 9, p), 900_000); // 15 min cap
90
+ });
91
+
92
+ it("floors at minDelayMs (never hammer)", () => {
93
+ const d = computeSurgeDelayMs({ ...SIGNAL_3MIN, retryAfterMs: 1_000 }, 1, {
94
+ minDelayMs: 30_000,
95
+ jitterRatio: 0,
96
+ });
97
+ assert.equal(d, 30_000);
98
+ });
99
+
100
+ it("jitter stays inside ±ratio and within bounds", () => {
101
+ const lo = computeSurgeDelayMs(SIGNAL_3MIN, 1, { jitterRatio: 0.2 }, 0);
102
+ const hi = computeSurgeDelayMs(SIGNAL_3MIN, 1, { jitterRatio: 0.2 }, 1);
103
+ assert.ok(lo >= 180_000 * 0.8 && lo < 180_000);
104
+ assert.ok(hi > 180_000 && hi <= 180_000 * 1.2);
105
+ });
106
+ });
107
+
108
+ describe("T3 — SurgeScheduler attempt cap", () => {
109
+ it("counts 1..maxAttempts then null", () => {
110
+ const s = new SurgeScheduler({ maxAttempts: 3 });
111
+ assert.equal(s.nextAttempt(), 1);
112
+ assert.equal(s.nextAttempt(), 2);
113
+ assert.equal(s.nextAttempt(), 3);
114
+ assert.equal(s.nextAttempt(), null);
115
+ assert.equal(s.attempts, 3);
116
+ });
117
+ });
118
+
119
+ // ─── T-surge-retry Wrapper behavior ─────────────────────────────────────────
120
+
121
+ describe("invokeWithSurgeRetry", () => {
122
+ it("retries through a 529 and succeeds (the incident scenario)", async () => {
123
+ const sleeps: number[] = [];
124
+ let calls = 0;
125
+ const result = await invokeWithSurgeRetry(
126
+ async () => {
127
+ calls += 1;
128
+ if (calls < 3) throw new Error(INCIDENT);
129
+ return "approved";
130
+ },
131
+ { policy: FAST_POLICY, sleep: async (ms) => void sleeps.push(ms) },
132
+ );
133
+ assert.equal(result, "approved");
134
+ assert.equal(calls, 3);
135
+ assert.deepEqual(sleeps, [100, 200]); // escalated, no jitter
136
+ });
137
+
138
+ it("rethrows non-surge errors immediately (no retry)", async () => {
139
+ const sleeps: number[] = [];
140
+ let calls = 0;
141
+ await assert.rejects(
142
+ invokeWithSurgeRetry(
143
+ async () => {
144
+ calls += 1;
145
+ throw new Error("ECONNREFUSED");
146
+ },
147
+ { policy: FAST_POLICY, sleep: async (ms) => void sleeps.push(ms) },
148
+ ),
149
+ /ECONNREFUSED/,
150
+ );
151
+ assert.equal(calls, 1);
152
+ assert.equal(sleeps.length, 0);
153
+ });
154
+
155
+ it("gives up after maxAttempts, fires onExhausted, rethrows last error", async () => {
156
+ const pauses: number[] = [];
157
+ let exhausted = false;
158
+ let calls = 0;
159
+ await assert.rejects(
160
+ invokeWithSurgeRetry(
161
+ async () => {
162
+ calls += 1;
163
+ throw new Error(INCIDENT);
164
+ },
165
+ {
166
+ policy: FAST_POLICY,
167
+ sleep: async (ms) => void pauses.push(ms),
168
+ onSurge: ({ attempt }) => assert.ok(attempt >= 1 && attempt <= 3),
169
+ onExhausted: () => {
170
+ exhausted = true;
171
+ },
172
+ },
173
+ ),
174
+ /overloaded_error/,
175
+ );
176
+ assert.equal(calls, 4); // initial + 3 retries
177
+ assert.deepEqual(pauses, [100, 200, 400]);
178
+ assert.equal(exhausted, true);
179
+ });
180
+ });
181
+
182
+ // ─── T8 Daemon-level: graph deps that surge once, then succeed ───────────────
183
+
184
+ describe("T8 — loop deps surviving a mid-graph 529", () => {
185
+ it("writeStep throws the incident once; retry wrapper completes the loop", async () => {
186
+ const { buildWriteReviewLoop, buildDryRunDeps } = await import("./graph.js");
187
+
188
+ const base = buildDryRunDeps({ maxIterations: 1 });
189
+ let writeCalls = 0;
190
+ const deps: LoopDeps = {
191
+ ...base,
192
+ write: async (plan, review) => {
193
+ writeCalls += 1;
194
+ if (writeCalls === 1) throw new Error(INCIDENT);
195
+ return base.write(plan, review);
196
+ },
197
+ };
198
+
199
+ const loop = buildWriteReviewLoop(deps);
200
+ const sleeps: number[] = [];
201
+ const state = await invokeWithSurgeRetry(
202
+ () =>
203
+ loop.invoke(
204
+ { request: "surge survival test" },
205
+ { configurable: { thread_id: "t8-surge" } },
206
+ ),
207
+ { policy: FAST_POLICY, sleep: async (ms) => void sleeps.push(ms) },
208
+ );
209
+
210
+ assert.equal(writeCalls, 2); // first surged, retry succeeded
211
+ assert.ok(state.review, "loop produced a review");
212
+ assert.deepEqual(sleeps, [100]);
213
+ });
214
+ });
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Surge auto-resume — 529 / overloaded_error detection, escalation backoff,
3
+ * and a retry wrapper for the daemon's graph invocations.
4
+ *
5
+ * Implements S2 + S4 of wiki/peak-hour-surge-auto-resume.md:
6
+ * seconds-scale blits stay in the provider client; minutes-scale surges are
7
+ * handled HERE with scheduled pauses (3 → 6 → 12 min, jittered, capped).
8
+ *
9
+ * Verdict vocabulary and patterns intentionally match:
10
+ * - harness/loop-runtime.ts 529 path (commit 9ae0ffd)
11
+ * - harness/e2e/glm-quota-scraper.ts parseMinimaxOverloadResetTime()
12
+ * - packages/providers/src/adapters.ts isOverloaded
13
+ *
14
+ * Wiki: wiki/peak-hour-surge-auto-resume.md
15
+ */
16
+
17
+ // ─── Classification ─────────────────────────────────────────────────────────
18
+
19
+ export interface SurgeSignal {
20
+ /** Parsed recovery delay in ms (midpoint of the stated range, or fallback) */
21
+ retryAfterMs: number;
22
+ /** True when the delay came from an explicit provider statement */
23
+ explicit: boolean;
24
+ /** Raw error text for logs */
25
+ sourceText: string;
26
+ }
27
+
28
+ const OVERLOADED_PATTERNS: RegExp[] = [
29
+ /529/,
30
+ /overloaded_error/i,
31
+ /peak.?hour.*surge/i,
32
+ /(?:overload|surge|busy)/i,
33
+ ];
34
+
35
+ const RECOVERY_RANGE = /recovers? within (\d+)\s*[\u2013-]\s*(\d+)\s*minutes/i;
36
+ const SIMPLE_DELAY = /retry (?:after|in) (\d+)\s*(seconds?|secs?|s)\b/i;
37
+ const RETRY_AFTER_MS = /retry.?after[^0-9]{0,12}(\d{4,})\s*ms/i;
38
+
39
+ /**
40
+ * Classify an unknown error as a transient provider surge.
41
+ * Returns null for anything that is not a 529/overload-class failure.
42
+ */
43
+ export function classifySurge(err: unknown): SurgeSignal | null {
44
+ const sourceText =
45
+ err instanceof Error
46
+ ? err.message
47
+ : typeof err === "string"
48
+ ? err
49
+ : String(err);
50
+
51
+ if (!OVERLOADED_PATTERNS.some((p) => p.test(sourceText))) {
52
+ return null;
53
+ }
54
+
55
+ // "recovers within 1–5 minutes" → midpoint (3 min)
56
+ const range = sourceText.match(RECOVERY_RANGE);
57
+ if (range) {
58
+ const min = Number.parseInt(range[1] as string, 10);
59
+ const max = Number.parseInt(range[2] as string, 10);
60
+ if (Number.isFinite(min) && Number.isFinite(max) && max >= min) {
61
+ return {
62
+ retryAfterMs: Math.round(((min + max) / 2) * 60_000),
63
+ explicit: true,
64
+ sourceText,
65
+ };
66
+ }
67
+ }
68
+
69
+ // "retry after 30 seconds"
70
+ const simple = sourceText.match(SIMPLE_DELAY);
71
+ if (simple) {
72
+ const secs = Number.parseInt(simple[1] as string, 10);
73
+ if (Number.isFinite(secs) && secs > 0) {
74
+ return {
75
+ retryAfterMs: secs * 1000,
76
+ explicit: true,
77
+ sourceText,
78
+ };
79
+ }
80
+ }
81
+
82
+ // "retry-after 120000ms" (header-style)
83
+ const ms = sourceText.match(RETRY_AFTER_MS);
84
+ if (ms) {
85
+ const val = Number.parseInt(ms[1] as string, 10);
86
+ if (Number.isFinite(val) && val > 0) {
87
+ return { retryAfterMs: val, explicit: true, sourceText };
88
+ }
89
+ }
90
+
91
+ // Overload-class error without a stated delay → conservative default
92
+ return { retryAfterMs: 120_000, explicit: false, sourceText };
93
+ }
94
+
95
+ // ─── Policy ─────────────────────────────────────────────────────────────────
96
+
97
+ export interface SurgePolicy {
98
+ /** Override the signal's parsed delay (ms). Default: use the signal. */
99
+ baseDelayMs?: number;
100
+ /** Delay multiplier per attempt. Default: 2 (3 → 6 → 12 min) */
101
+ multiplier: number;
102
+ /** Floor for any wait. Default: 30_000 (never hammer a surging provider) */
103
+ minDelayMs: number;
104
+ /** Ceiling for any wait. Default: 15 min */
105
+ maxDelayMs: number;
106
+ /** ± ratio applied as jitter. Default: 0.2 */
107
+ jitterRatio: number;
108
+ /** Max surge pauses before giving up. Default: 5 */
109
+ maxAttempts: number;
110
+ }
111
+
112
+ export const DEFAULT_SURGE_POLICY: SurgePolicy = {
113
+ multiplier: 2,
114
+ minDelayMs: 30_000,
115
+ maxDelayMs: 15 * 60_000,
116
+ jitterRatio: 0.2,
117
+ maxAttempts: 5,
118
+ };
119
+
120
+ /**
121
+ * Deterministic delay computation (unit-testable, no timers).
122
+ * `rand` in [0,1] controls jitter; omit it for zero jitter.
123
+ */
124
+ export function computeSurgeDelayMs(
125
+ signal: SurgeSignal,
126
+ attempt: number,
127
+ policy: Partial<SurgePolicy> = {},
128
+ rand?: number,
129
+ ): number {
130
+ const p = { ...DEFAULT_SURGE_POLICY, ...policy };
131
+ const base = p.baseDelayMs ?? signal.retryAfterMs;
132
+ const escalated = base * p.multiplier ** Math.max(0, attempt - 1);
133
+ const clamped = Math.min(Math.max(escalated, p.minDelayMs), p.maxDelayMs);
134
+ if (rand === undefined || p.jitterRatio === 0) return clamped;
135
+ const jitter = clamped * p.jitterRatio * (2 * rand - 1);
136
+ return Math.min(Math.max(clamped + jitter, p.minDelayMs), p.maxDelayMs);
137
+ }
138
+
139
+ // ─── Scheduler ──────────────────────────────────────────────────────────────
140
+
141
+ /** Attempt counter with escalation; persists across a task's lifetime. */
142
+ export class SurgeScheduler {
143
+ private attempt = 0;
144
+ private readonly policy: SurgePolicy;
145
+
146
+ constructor(policy: Partial<SurgePolicy> = {}) {
147
+ this.policy = { ...DEFAULT_SURGE_POLICY, ...policy };
148
+ }
149
+
150
+ /** Next attempt number, or null when maxAttempts is exhausted. */
151
+ nextAttempt(): number | null {
152
+ if (this.attempt >= this.policy.maxAttempts) return null;
153
+ this.attempt += 1;
154
+ return this.attempt;
155
+ }
156
+
157
+ get attempts(): number {
158
+ return this.attempt;
159
+ }
160
+
161
+ delayFor(signal: SurgeSignal, rand?: number): number {
162
+ return computeSurgeDelayMs(signal, this.attempt, this.policy, rand);
163
+ }
164
+ }
165
+
166
+ // ─── Retry wrapper ──────────────────────────────────────────────────────────
167
+
168
+ export interface SurgeRetryOptions {
169
+ policy?: Partial<SurgePolicy>;
170
+ /** Called before each surge pause (logging / notifications) */
171
+ onSurge?: (info: {
172
+ attempt: number;
173
+ delayMs: number;
174
+ signal: SurgeSignal;
175
+ }) => void;
176
+ /** Called once when attempts are exhausted (before rethrow) */
177
+ onExhausted?: (signal: SurgeSignal) => void;
178
+ /** Injectable sleep for tests. Default: real setTimeout */
179
+ sleep?: (ms: number) => Promise<void>;
180
+ }
181
+
182
+ const realSleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
183
+
184
+ /**
185
+ * Run `fn`, retrying only on surge-classified failures with escalated,
186
+ * jittered pauses. Non-surge errors rethrow immediately. On exhaustion the
187
+ * last error is rethrown after `onExhausted`.
188
+ */
189
+ export async function invokeWithSurgeRetry<T>(
190
+ fn: () => Promise<T>,
191
+ opts: SurgeRetryOptions = {},
192
+ ): Promise<T> {
193
+ const scheduler = new SurgeScheduler(opts.policy);
194
+ const sleep = opts.sleep ?? realSleep;
195
+
196
+ for (;;) {
197
+ try {
198
+ return await fn();
199
+ } catch (err) {
200
+ const signal = classifySurge(err);
201
+ if (!signal) throw err; // not a surge — fail fast
202
+
203
+ const attempt = scheduler.nextAttempt();
204
+ if (attempt === null) {
205
+ opts.onExhausted?.(signal);
206
+ throw err;
207
+ }
208
+
209
+ const delayMs = scheduler.delayFor(
210
+ signal,
211
+ Math.random(), // jitter draw
212
+ );
213
+ opts.onSurge?.({ attempt, delayMs, signal });
214
+ await sleep(delayMs);
215
+ }
216
+ }
217
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -89,7 +89,13 @@
89
89
  "packages/*"
90
90
  ],
91
91
  "dependencies": {
92
+ "@langchain/core": "^1.2.9",
93
+ "@langchain/langgraph": "^1.4.13",
94
+ "@langchain/langgraph-checkpoint": "^1.1.5",
95
+ "@langchain/openai": "^1.5.10",
92
96
  "chokidar": "^5.0.0",
93
- "deepagents": "^1.10.5"
97
+ "deepagents": "^1.10.5",
98
+ "langchain": "^1.5.10",
99
+ "zod": "^4.5.4"
94
100
  }
95
101
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/a2a-adapter",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "description": "Google Agent-to-Agent (A2A) protocol adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/architecture-generator",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Generate ADR and Mermaid diagrams from project analysis",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/auth",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "pi-harness-runtime — auth",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-refactor",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "description": "Autonomous refactoring engine",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-runtime",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Autonomous Operations Runtime — task inbox, lease management, and worker lifecycle (RFC-0101)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cache-strategy",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "description": "Smart caching with TTL and invalidation strategies (RFC-0022)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/capability-registry",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/checkpoint",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Enhanced checkpoint system with incremental snapshots, diff-based storage, and recovery strategies",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cli-plugin-sdk",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "description": "CLI Plugin SDK for pi-harness — install, list, remove, update, invoke plugins",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard-plugin",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-generation",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Code generation pipeline for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-review",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Automated code review engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/codex-adapter",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "description": "OpenAI Codex provider adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moocoding/config-capture",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Auto-capture API-fetched configuration values to AGENTS.md",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/context-compiler",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Bounded context selection engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/context-discovery",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/context-manager",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Context Window Manager — prevents model context overflow via compaction and resume prompts (RFC-0010)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/cookie-sanitizer",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "pi-harness-runtime — cookie sanitizer (provider-quota cookie file normaliser)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/cost-optimizer",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Cost Optimizer for pi-harness-runtime — budget tracking, forecasting, and model selection optimization",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/dependency-analyzer",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/django-plugin",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Django framework analysis — models, management commands, settings",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/doc-generator",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Auto-Doc Generator — generate documentation from source code (RFC-0014)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/evaluation-engine",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
4
4
  "description": "Evaluation engine for pi-harness runtime (RFC-0057)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",