pi-harness-runtime 1.1.39 → 1.1.41
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/harness/langchain/daemon.ts +1 -1
- package/harness/langchain/widget.test.ts +25 -18
- package/harness/langchain/widget.ts +61 -44
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/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/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/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/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/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/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/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/intent-analyzer/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/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/milestone-manager/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/okf-indexer/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/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/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/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/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
|
@@ -25,7 +25,6 @@ const stubTheme = {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
describe("T14 — LoopWidget", () => {
|
|
28
|
-
|
|
29
28
|
let widget: LoopWidget;
|
|
30
29
|
|
|
31
30
|
beforeEach(() => {
|
|
@@ -58,14 +57,14 @@ describe("T14 — LoopWidget", () => {
|
|
|
58
57
|
widget.setSurgePause(new Date(Date.now() + 30 * 60_000)); // 30 min
|
|
59
58
|
const lines = widget.renderWidget(80, stubTheme);
|
|
60
59
|
// Label is "surge (in 30m)"
|
|
61
|
-
assert.ok(lines.some(l => l.includes("surge") && l.includes("in 30m")));
|
|
60
|
+
assert.ok(lines.some((l) => l.includes("surge") && l.includes("in 30m")));
|
|
62
61
|
});
|
|
63
62
|
|
|
64
63
|
it("setError shows error detail", () => {
|
|
65
64
|
widget.setError("model timeout");
|
|
66
65
|
const lines = widget.renderWidget(80, stubTheme);
|
|
67
|
-
assert.ok(lines.some(l => l.includes("error")));
|
|
68
|
-
assert.ok(lines.some(l => l.includes("model timeout")));
|
|
66
|
+
assert.ok(lines.some((l) => l.includes("error")));
|
|
67
|
+
assert.ok(lines.some((l) => l.includes("model timeout")));
|
|
69
68
|
});
|
|
70
69
|
|
|
71
70
|
it("setComplete approved shows ✓ loop complete", () => {
|
|
@@ -101,10 +100,13 @@ describe("T14 — LoopWidget", () => {
|
|
|
101
100
|
// Files accumulate across iterations (same codebase); only counters reset.
|
|
102
101
|
// After reset, a.ts shows with 0 write steps and 0 blockers.
|
|
103
102
|
const lines = widget.renderWidget(80, stubTheme);
|
|
104
|
-
const fileLines = lines.filter(l => l.includes("a.ts"));
|
|
103
|
+
const fileLines = lines.filter((l) => l.includes("a.ts"));
|
|
105
104
|
assert.ok(fileLines.length > 0, "file should still appear");
|
|
106
105
|
// No blocker count in the file row (reset to 0)
|
|
107
|
-
assert.ok(
|
|
106
|
+
assert.ok(
|
|
107
|
+
!fileLines.some((l) => l.includes("!2")),
|
|
108
|
+
"blocker count should be reset",
|
|
109
|
+
);
|
|
108
110
|
});
|
|
109
111
|
|
|
110
112
|
// ─── File record tracking ──────────────────────────────────────────────
|
|
@@ -112,29 +114,33 @@ describe("T14 — LoopWidget", () => {
|
|
|
112
114
|
it("recordWrite shows file in widget", () => {
|
|
113
115
|
widget.recordWrite("src/foo.ts");
|
|
114
116
|
const lines = widget.renderWidget(80, stubTheme);
|
|
115
|
-
assert.ok(lines.some(l => l.includes("foo.ts")));
|
|
117
|
+
assert.ok(lines.some((l) => l.includes("foo.ts")));
|
|
116
118
|
});
|
|
117
119
|
|
|
118
120
|
it("recordWrite accumulates across calls", () => {
|
|
119
121
|
widget.recordWrite("src/bar.ts");
|
|
120
122
|
widget.recordWrite("src/bar.ts");
|
|
121
123
|
const lines = widget.renderWidget(80, stubTheme);
|
|
122
|
-
assert.ok(lines.some(l => l.includes("bar.ts") && l.includes("✍2")));
|
|
124
|
+
assert.ok(lines.some((l) => l.includes("bar.ts") && l.includes("✍2")));
|
|
123
125
|
});
|
|
124
126
|
|
|
125
127
|
it("recordBlockers shows blocker count", () => {
|
|
126
128
|
widget.recordBlockers("src/bad.ts", 2);
|
|
127
129
|
const lines = widget.renderWidget(80, stubTheme);
|
|
128
|
-
assert.ok(lines.some(l => l.includes("bad.ts") && l.includes("!2")));
|
|
130
|
+
assert.ok(lines.some((l) => l.includes("bad.ts") && l.includes("!2")));
|
|
129
131
|
});
|
|
130
132
|
|
|
131
133
|
it("recordReviewPass clears blockers and increments passes", () => {
|
|
132
134
|
widget.recordBlockers("src/ok.ts", 1);
|
|
133
135
|
widget.recordReviewPass("src/ok.ts");
|
|
134
136
|
const lines = widget.renderWidget(80, stubTheme);
|
|
135
|
-
assert.ok(lines.some(l => l.includes("ok.ts") && l.includes("🔍1")));
|
|
137
|
+
assert.ok(lines.some((l) => l.includes("ok.ts") && l.includes("🔍1")));
|
|
136
138
|
// No blocker count
|
|
137
|
-
assert.ok(
|
|
139
|
+
assert.ok(
|
|
140
|
+
!lines.some(
|
|
141
|
+
(l) => l.includes("ok.ts") && l.includes("!") && !l.includes("🔍"),
|
|
142
|
+
),
|
|
143
|
+
);
|
|
138
144
|
});
|
|
139
145
|
|
|
140
146
|
// ─── Summary counts ────────────────────────────────────────────────────
|
|
@@ -147,7 +153,7 @@ describe("T14 — LoopWidget", () => {
|
|
|
147
153
|
it("errors shown as ●NE", () => {
|
|
148
154
|
widget.recordBlockers("src/err.ts", 3);
|
|
149
155
|
const lines = widget.renderWidget(80, stubTheme);
|
|
150
|
-
assert.ok(lines.some(l => l.includes("●3E")));
|
|
156
|
+
assert.ok(lines.some((l) => l.includes("●3E")));
|
|
151
157
|
});
|
|
152
158
|
|
|
153
159
|
// ─── Surge pause ──────────────────────────────────────────────────────
|
|
@@ -156,7 +162,7 @@ describe("T14 — LoopWidget", () => {
|
|
|
156
162
|
const resetAt = new Date(Date.now() + 90 * 60_000); // 90 minutes → "in 1h 30m"
|
|
157
163
|
widget.setSurgePause(resetAt);
|
|
158
164
|
const lines = widget.renderWidget(80, stubTheme);
|
|
159
|
-
const surgeLine = lines.find(l => l.includes("surge"));
|
|
165
|
+
const surgeLine = lines.find((l) => l.includes("surge"));
|
|
160
166
|
assert.ok(surgeLine !== undefined);
|
|
161
167
|
assert.match(surgeLine, /\(in \d+h/); // "in 1h 30m" matches
|
|
162
168
|
});
|
|
@@ -166,7 +172,7 @@ describe("T14 — LoopWidget", () => {
|
|
|
166
172
|
widget.setSurgePause(resetAt);
|
|
167
173
|
const lines = widget.renderWidget(80, stubTheme);
|
|
168
174
|
// Label format: "surge (now)"
|
|
169
|
-
assert.ok(lines.some(l => l.includes("surge") && l.includes("(now)")));
|
|
175
|
+
assert.ok(lines.some((l) => l.includes("surge") && l.includes("(now)")));
|
|
170
176
|
});
|
|
171
177
|
|
|
172
178
|
// ─── Console fallback ─────────────────────────────────────────────────
|
|
@@ -185,7 +191,9 @@ describe("T14 — LoopWidget", () => {
|
|
|
185
191
|
// ─── Width / truncation ───────────────────────────────────────────────
|
|
186
192
|
|
|
187
193
|
it("truncates long file names with …", () => {
|
|
188
|
-
widget.recordWrite(
|
|
194
|
+
widget.recordWrite(
|
|
195
|
+
"/very/long/path/to/a/very/long/file/name/that/exceeds/width.ts",
|
|
196
|
+
);
|
|
189
197
|
const lines = widget.renderWidget(40, stubTheme);
|
|
190
198
|
for (const line of lines) {
|
|
191
199
|
const stripped = line.replace(/\x1b\[[0-9;]*m/g, "");
|
|
@@ -202,7 +210,7 @@ describe("T14 — LoopWidget", () => {
|
|
|
202
210
|
widget.reset();
|
|
203
211
|
const lines = widget.renderWidget(80, stubTheme);
|
|
204
212
|
assert.match(lines[0], /idle/);
|
|
205
|
-
assert.ok(!lines.some(l => l.includes("a.ts")));
|
|
213
|
+
assert.ok(!lines.some((l) => l.includes("a.ts")));
|
|
206
214
|
});
|
|
207
215
|
|
|
208
216
|
// ─── makeRenderer ─────────────────────────────────────────────────────
|
|
@@ -234,11 +242,10 @@ describe("T14 — LoopWidget", () => {
|
|
|
234
242
|
|
|
235
243
|
it("getLoopWidget returns the same instance", () => {
|
|
236
244
|
// Dynamic import to avoid module caching issues
|
|
237
|
-
import("./widget.js").then(m => {
|
|
245
|
+
import("./widget.js").then((m) => {
|
|
238
246
|
const a = m.getLoopWidget();
|
|
239
247
|
const b = m.getLoopWidget();
|
|
240
248
|
assert.strictEqual(a, b);
|
|
241
249
|
});
|
|
242
250
|
});
|
|
243
|
-
|
|
244
251
|
});
|
|
@@ -33,11 +33,14 @@ function visibleWidth(s: string): number {
|
|
|
33
33
|
// Skip CSI sequences: \x1b[ <params> <final>
|
|
34
34
|
// Valid final bytes: m (SGR), H (CUP), J (ED), A/B/C/D (CUU/CUD/CUF/CUB)
|
|
35
35
|
i++;
|
|
36
|
-
|
|
36
|
+
while (i < s.length && !/[a-zA-Z@]/.test(s[i])) i++;
|
|
37
37
|
if (i < s.length) i++; // skip final byte
|
|
38
38
|
continue;
|
|
39
39
|
}
|
|
40
|
-
if (cp <= 0x1f || cp === 0x7f) {
|
|
40
|
+
if (cp <= 0x1f || cp === 0x7f) {
|
|
41
|
+
i++;
|
|
42
|
+
continue;
|
|
43
|
+
} // C0 + DEL = 0
|
|
41
44
|
w += cp > 0xffff ? 2 : 1;
|
|
42
45
|
i += cp > 0xffff ? 2 : 1; // advance by code point, not UTF-16 code unit
|
|
43
46
|
}
|
|
@@ -170,7 +173,7 @@ export class LoopWidget {
|
|
|
170
173
|
const labels = {
|
|
171
174
|
approved: "✓ loop complete",
|
|
172
175
|
rejected: "✗ loop rejected",
|
|
173
|
-
|
|
176
|
+
max_iterations: `⚠ max iterations (${this.maxIterations})`,
|
|
174
177
|
};
|
|
175
178
|
this.stepLabel = labels[verdict];
|
|
176
179
|
this.render();
|
|
@@ -197,7 +200,10 @@ export class LoopWidget {
|
|
|
197
200
|
* Line 2: ` surge pause — resets 19:17` — surge detail (when applicable)
|
|
198
201
|
* Line 3: ` ●surge.ts ✍2 🔍3 !1` — file rows (up to 5)
|
|
199
202
|
*/
|
|
200
|
-
renderWidget(
|
|
203
|
+
renderWidget(
|
|
204
|
+
width: number,
|
|
205
|
+
theme: { fg: (color: ColorKey, s: string) => string },
|
|
206
|
+
): string[] {
|
|
201
207
|
const dim = (s: string) => theme.fg("dim", s);
|
|
202
208
|
const red = (s: string) => theme.fg("error", s);
|
|
203
209
|
const yellow = (s: string) => theme.fg("warning", s);
|
|
@@ -208,21 +214,18 @@ export class LoopWidget {
|
|
|
208
214
|
const lines: string[] = [];
|
|
209
215
|
|
|
210
216
|
// ── Header ──────────────────────────────────────────────────────────────
|
|
211
|
-
const iterStr =
|
|
212
|
-
|
|
213
|
-
|
|
217
|
+
const iterStr =
|
|
218
|
+
this.iteration > 0
|
|
219
|
+
? dim(`iter ${this.iteration}/${this.maxIterations}`)
|
|
220
|
+
: "";
|
|
214
221
|
// Use stepLabel if set (custom phase label, surge detail, error message)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
222
|
+
const phaseStr = this.stepLabel
|
|
223
|
+
? this.phaseIcon(this.phase) + " " + this.stepLabel
|
|
224
|
+
: this.phaseIcon(this.phase) + " " + this.phaseLabel(this.phase);
|
|
218
225
|
|
|
219
226
|
// Summary chunks (matches pi-lens style: !NW ●ME)
|
|
220
|
-
const errorChunk = this.errors > 0
|
|
221
|
-
|
|
222
|
-
: "";
|
|
223
|
-
const warningChunk = this.warnings > 0
|
|
224
|
-
? yellow(`!${this.warnings}W`)
|
|
225
|
-
: "";
|
|
227
|
+
const errorChunk = this.errors > 0 ? red(`●${this.errors}E`) : "";
|
|
228
|
+
const warningChunk = this.warnings > 0 ? yellow(`!${this.warnings}W`) : "";
|
|
226
229
|
const summary = errorChunk
|
|
227
230
|
? errorChunk + (warningChunk ? " " + warningChunk : "")
|
|
228
231
|
: warningChunk
|
|
@@ -231,12 +234,9 @@ export class LoopWidget {
|
|
|
231
234
|
? green("✓")
|
|
232
235
|
: dim("…");
|
|
233
236
|
|
|
234
|
-
const parts = [
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
phaseStr,
|
|
238
|
-
summary,
|
|
239
|
-
].filter(Boolean).join(" ");
|
|
237
|
+
const parts = [cyan("harness"), iterStr, phaseStr, summary]
|
|
238
|
+
.filter(Boolean)
|
|
239
|
+
.join(" ");
|
|
240
240
|
|
|
241
241
|
lines.push(this.fitLine(` ${parts}`, w));
|
|
242
242
|
|
|
@@ -257,11 +257,12 @@ export class LoopWidget {
|
|
|
257
257
|
|
|
258
258
|
for (const rec of sorted) {
|
|
259
259
|
const tier = this.classifyFileTier(rec);
|
|
260
|
-
const dot =
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
const dot =
|
|
261
|
+
tier === "blocking"
|
|
262
|
+
? red("●")
|
|
263
|
+
: tier === "warning"
|
|
264
|
+
? yellow("!")
|
|
265
|
+
: dim("·");
|
|
265
266
|
const base = this.fileBasename(rec.filePath);
|
|
266
267
|
const steps = rec.writeSteps > 0 ? dim(` ✍${rec.writeSteps}`) : "";
|
|
267
268
|
const reviews = rec.reviewsPassed > 0 ? dim(` 🔍${rec.reviewsPassed}`) : "";
|
|
@@ -276,25 +277,24 @@ export class LoopWidget {
|
|
|
276
277
|
/** Console fallback (standalone mode). */
|
|
277
278
|
toConsoleString(): string {
|
|
278
279
|
const phase = this.phaseIcon(this.phase) + " " + this.stepLabel;
|
|
279
|
-
const iter =
|
|
280
|
+
const iter =
|
|
281
|
+
this.iteration > 0 ? ` [iter ${this.iteration}/${this.maxIterations}]` : "";
|
|
280
282
|
const err = this.errors > 0 ? ` ●${this.errors}E` : "";
|
|
281
283
|
const warn = this.warnings > 0 ? ` !${this.warnings}W` : "";
|
|
282
284
|
const files = [...this.files.values()]
|
|
283
|
-
.filter(r => r.writeSteps > 0 || r.blockers > 0)
|
|
285
|
+
.filter((r) => r.writeSteps > 0 || r.blockers > 0)
|
|
284
286
|
.sort((a, b) => b.touchedAt - a.touchedAt)
|
|
285
287
|
.slice(0, 3)
|
|
286
|
-
.map(
|
|
288
|
+
.map(
|
|
289
|
+
(r) => `${this.fileBasename(r.filePath)}(${r.writeSteps}w/${r.blockers}b)`,
|
|
290
|
+
)
|
|
287
291
|
.join(", ");
|
|
288
292
|
|
|
289
|
-
const parts = [
|
|
290
|
-
`harness${iter}`,
|
|
291
|
-
phase,
|
|
292
|
-
].filter(Boolean).join(" ");
|
|
293
|
+
const parts = [`harness${iter}`, phase].filter(Boolean).join(" ");
|
|
293
294
|
|
|
294
|
-
return [
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
].filter(Boolean).join("\n");
|
|
295
|
+
return [parts + err + warn, files ? ` files: ${files}` : ""]
|
|
296
|
+
.filter(Boolean)
|
|
297
|
+
.join("\n");
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
// ─── Pi host widget factory (used by index.ts / ExtensionUIContext) ────────
|
|
@@ -315,7 +315,10 @@ export class LoopWidget {
|
|
|
315
315
|
* on every frame; `invalidate` is called by the harness to trigger a re-render.
|
|
316
316
|
*/
|
|
317
317
|
makeRenderer(): {
|
|
318
|
-
factory: (
|
|
318
|
+
factory: (
|
|
319
|
+
tui: TUI,
|
|
320
|
+
theme: Theme,
|
|
321
|
+
) => {
|
|
319
322
|
render: (width: number) => string[];
|
|
320
323
|
invalidate: () => void;
|
|
321
324
|
dispose: () => void;
|
|
@@ -323,7 +326,9 @@ export class LoopWidget {
|
|
|
323
326
|
invalidate: () => void;
|
|
324
327
|
} {
|
|
325
328
|
// Shared invalidate trigger — both the harness and the pi-tui component call this
|
|
326
|
-
const invalidate = () => {
|
|
329
|
+
const invalidate = () => {
|
|
330
|
+
/* mark dirty for next frame */
|
|
331
|
+
};
|
|
327
332
|
|
|
328
333
|
const factory = (_tui: TUI, theme: Theme) => {
|
|
329
334
|
type ColorKey = "dim" | "error" | "warning" | "success" | "accent";
|
|
@@ -334,12 +339,16 @@ export class LoopWidget {
|
|
|
334
339
|
};
|
|
335
340
|
|
|
336
341
|
// Called by harness to signal the widget needs to re-render
|
|
337
|
-
const widgetInvalidate = () => {
|
|
342
|
+
const widgetInvalidate = () => {
|
|
343
|
+
/* trigger invalidate */
|
|
344
|
+
};
|
|
338
345
|
|
|
339
346
|
return {
|
|
340
347
|
render,
|
|
341
348
|
invalidate: widgetInvalidate,
|
|
342
|
-
dispose: () => {
|
|
349
|
+
dispose: () => {
|
|
350
|
+
/* clean up */
|
|
351
|
+
},
|
|
343
352
|
};
|
|
344
353
|
};
|
|
345
354
|
|
|
@@ -371,7 +380,9 @@ export class LoopWidget {
|
|
|
371
380
|
return segs[segs.length - 1] ?? filePath;
|
|
372
381
|
}
|
|
373
382
|
|
|
374
|
-
private classifyFileTier(
|
|
383
|
+
private classifyFileTier(
|
|
384
|
+
rec: FileStepRecord,
|
|
385
|
+
): "blocking" | "warning" | "clean" {
|
|
375
386
|
if (rec.blockers > 0) return "blocking";
|
|
376
387
|
if (rec.writeSteps > 0 || rec.reviewsPassed > 0) return "warning";
|
|
377
388
|
return "clean";
|
|
@@ -434,7 +445,13 @@ export class LoopWidget {
|
|
|
434
445
|
const cp = line.codePointAt(i)!;
|
|
435
446
|
if (cp === 0x1b) {
|
|
436
447
|
// Skip ANSI sequences (don't count toward width)
|
|
437
|
-
while (
|
|
448
|
+
while (
|
|
449
|
+
i < line.length &&
|
|
450
|
+
line[i] !== "m" &&
|
|
451
|
+
line[i] !== "H" &&
|
|
452
|
+
line[i] !== "J"
|
|
453
|
+
)
|
|
454
|
+
i++;
|
|
438
455
|
continue;
|
|
439
456
|
}
|
|
440
457
|
const charW = cp > 0xffff ? 2 : 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.41",
|
|
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",
|