pi-harness-runtime 1.1.134 → 1.1.135
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/index.ts +100 -47
- 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/jev-judge/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/qdrant-skills/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/skills/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/trajectory/package.json +1 -1
- package/packages/tui/dist/harness-header.d.ts +41 -0
- package/packages/tui/dist/harness-header.d.ts.map +1 -0
- package/packages/tui/dist/harness-header.js +184 -0
- package/packages/tui/dist/harness-header.js.map +1 -0
- package/packages/tui/dist/index.d.ts +9 -0
- package/packages/tui/dist/index.d.ts.map +1 -0
- package/packages/tui/dist/index.js +9 -0
- package/packages/tui/dist/index.js.map +1 -0
- package/packages/tui/package.json +1 -1
- package/packages/tui/src/harness-header.ts +255 -0
- package/packages/tui/src/index.ts +9 -0
- 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
package/index.ts
CHANGED
|
@@ -227,21 +227,15 @@ async function initQdrant(): Promise<void> {
|
|
|
227
227
|
const { getOpenAIApiKey } = await import("./packages/qdrant-skills/src/embedder.js");
|
|
228
228
|
const embeddingKey = getOpenAIApiKey();
|
|
229
229
|
if (embeddingKey) {
|
|
230
|
-
|
|
230
|
+
logStartup("[pi-harness] Qdrant vector search ready");
|
|
231
231
|
} else {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
console.error('[pi-harness] For vector search: echo "{openai-api-key}" > ~/.pi-harness-runtime/keys/openai-api-key.txt');
|
|
232
|
+
logStartup("[pi-harness] Qdrant ready (no embedding key — skills won't be vector-indexed)");
|
|
233
|
+
logStartup('[pi-harness] For vector search: echo "{openai-api-key}" > ~/.pi-harness-runtime/keys/openai-api-key.txt');
|
|
235
234
|
}
|
|
236
235
|
} else {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
` echo "{cluster-url}" > ${home}/.pi-harness-runtime/keys/qdrant-cluster-url.txt`
|
|
241
|
-
);
|
|
242
|
-
console.error(
|
|
243
|
-
` echo "{api-key}" > ${home}/.pi-harness-runtime/keys/qdrant-api-key.txt`
|
|
244
|
-
);
|
|
236
|
+
logStartup("[pi-harness] Qdrant not configured. Set keys to enable vector skill search:");
|
|
237
|
+
logStartup(` echo "{cluster-url}" > ~/.pi-harness-runtime/keys/qdrant-cluster-url.txt`);
|
|
238
|
+
logStartup(` echo "{api-key}" > ~/.pi-harness-runtime/keys/qdrant-api-key.txt`);
|
|
245
239
|
}
|
|
246
240
|
} catch {
|
|
247
241
|
// qdrant-skills not available
|
|
@@ -250,7 +244,7 @@ async function initQdrant(): Promise<void> {
|
|
|
250
244
|
|
|
251
245
|
// --- telegram-notifications: Telegram bot for harness event notifications ------------
|
|
252
246
|
// Sends Telegram messages when jobs complete, tasks finish, or human input is needed.
|
|
253
|
-
let
|
|
247
|
+
let _notificationCenter: unknown = null;
|
|
254
248
|
async function initTelegram(): Promise<void> {
|
|
255
249
|
try {
|
|
256
250
|
const { NotificationCenter } = await import("./packages/notification/dist/index.js");
|
|
@@ -262,19 +256,11 @@ async function initTelegram(): Promise<void> {
|
|
|
262
256
|
const chatIdPath = `${keysDir}/telegram-chat-id.txt`;
|
|
263
257
|
|
|
264
258
|
if (!existsSync(botTokenPath) || !existsSync(chatIdPath)) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
`[pi-harness] chat-id: message @userinfobot → reply shows your ID`
|
|
271
|
-
);
|
|
272
|
-
console.error(
|
|
273
|
-
`[pi-harness] echo "{bot-token}" > ${home}/.pi-harness-runtime/keys/telegram-bot-token.txt`
|
|
274
|
-
);
|
|
275
|
-
console.error(
|
|
276
|
-
`[pi-harness] echo "{chat-id}" > ${home}/.pi-harness-runtime/keys/telegram-chat-id.txt`
|
|
277
|
-
);
|
|
259
|
+
logStartup("[pi-harness] Telegram notifications not configured:");
|
|
260
|
+
logStartup(`[pi-harness] bot-token: create @BotFather bot → get token`);
|
|
261
|
+
logStartup(`[pi-harness] chat-id: message @userinfobot → reply shows your ID`);
|
|
262
|
+
logStartup(`[pi-harness] echo "{bot-token}" > ~/.pi-harness-runtime/keys/telegram-bot-token.txt`);
|
|
263
|
+
logStartup(`[pi-harness] echo "{chat-id}" > ~/.pi-harness-runtime/keys/telegram-chat-id.txt`);
|
|
278
264
|
return;
|
|
279
265
|
}
|
|
280
266
|
|
|
@@ -282,7 +268,7 @@ async function initTelegram(): Promise<void> {
|
|
|
282
268
|
const chatId = readFileSync(chatIdPath, "utf8").trim();
|
|
283
269
|
|
|
284
270
|
if (!botToken || !chatId) {
|
|
285
|
-
|
|
271
|
+
logStartup("[pi-harness] Telegram: bot token or chat ID is empty — skipping");
|
|
286
272
|
return;
|
|
287
273
|
}
|
|
288
274
|
|
|
@@ -304,10 +290,10 @@ async function initTelegram(): Promise<void> {
|
|
|
304
290
|
return;
|
|
305
291
|
}
|
|
306
292
|
|
|
307
|
-
|
|
308
|
-
|
|
293
|
+
_notificationCenter = center;
|
|
294
|
+
logStartup(`[pi-harness] Telegram notifications ready`);
|
|
309
295
|
} catch (err) {
|
|
310
|
-
|
|
296
|
+
logStartup("[pi-harness] Telegram: init failed:", err instanceof Error ? err.message : String(err));
|
|
311
297
|
}
|
|
312
298
|
}
|
|
313
299
|
|
|
@@ -321,17 +307,15 @@ async function initHoncho(pi: { events: { emit(name: string, data: unknown): voi
|
|
|
321
307
|
const keyPath = `${home}/.pi-harness-runtime/keys/honcho-api-key.txt`;
|
|
322
308
|
|
|
323
309
|
if (!existsSync(keyPath)) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
`[pi-harness] Then: echo "{api-key}" > ${home}/.pi-harness-runtime/keys/honcho-api-key.txt`
|
|
328
|
-
);
|
|
310
|
+
logStartup("[pi-harness] Honcho memory not configured:");
|
|
311
|
+
logStartup("[pi-harness] Get key: https://app.honcho.dev/api-keys");
|
|
312
|
+
logStartup(`[pi-harness] Then: echo "{api-key}" > ~/.pi-harness-runtime/keys/honcho-api-key.txt`);
|
|
329
313
|
return;
|
|
330
314
|
}
|
|
331
315
|
|
|
332
316
|
const apiKey = readFileSync(keyPath, "utf8").trim();
|
|
333
317
|
if (!apiKey) {
|
|
334
|
-
|
|
318
|
+
logStartup("[pi-harness] Honcho: API key is empty — skipping");
|
|
335
319
|
return;
|
|
336
320
|
}
|
|
337
321
|
|
|
@@ -348,9 +332,9 @@ async function initHoncho(pi: { events: { emit(name: string, data: unknown): voi
|
|
|
348
332
|
};
|
|
349
333
|
pi.events.emit("pi-mcp-adapter:runtime-register:v1", request);
|
|
350
334
|
});
|
|
351
|
-
|
|
335
|
+
logStartup("[pi-harness] Honcho memory ready (peer/user memory via mcp.honcho.dev)");
|
|
352
336
|
} catch (err) {
|
|
353
|
-
|
|
337
|
+
logStartup("[pi-harness] Honcho: init failed:", err instanceof Error ? err.message : String(err));
|
|
354
338
|
}
|
|
355
339
|
}
|
|
356
340
|
|
|
@@ -807,12 +791,22 @@ function processCompletionFile(filePath: string, pi: ExtensionAPI): void {
|
|
|
807
791
|
// --- Debug logging (file only, no console override) ---------------
|
|
808
792
|
// Logs written to file only. Real console output preserved for pi's TUI.
|
|
809
793
|
import { homedir } from "node:os";
|
|
810
|
-
import { existsSync, mkdirSync, symlinkSync } from "node:fs";
|
|
794
|
+
import { existsSync, mkdirSync, readFileSync, symlinkSync } from "node:fs";
|
|
811
795
|
import { join, dirname } from "node:path";
|
|
812
796
|
|
|
813
797
|
// --- Harness Runtime State --------------------------------------------
|
|
814
798
|
const HARNESS_ROOT_DIR = join(homedir(), ".pi-harness-runtime");
|
|
815
799
|
|
|
800
|
+
/** Startup messages collected during init — shown on session_start via ctx.ui.notify */
|
|
801
|
+
const startupMessages: string[] = [];
|
|
802
|
+
|
|
803
|
+
/** Log a harness startup message both to stderr (for logs) and to startupMessages (for UI) */
|
|
804
|
+
function logStartup(...parts: string[]): void {
|
|
805
|
+
const msg = parts.join(" ");
|
|
806
|
+
console.error(msg);
|
|
807
|
+
startupMessages.push(msg);
|
|
808
|
+
}
|
|
809
|
+
|
|
816
810
|
interface HarnessSession {
|
|
817
811
|
jobId: string;
|
|
818
812
|
machine: JobStateMachine;
|
|
@@ -866,17 +860,20 @@ const TRAJECTORY_DIR = join(homedir(), ".pi-harness-runtime", "trajectory");
|
|
|
866
860
|
const PI_SKILLS_DIR = join(homedir(), ".pi", "skills");
|
|
867
861
|
|
|
868
862
|
// --- Print minimal ASCII banner (shows every startup, matching pi.dev style) -------
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
const pkgPath =
|
|
872
|
-
let version = "?.?.?";
|
|
863
|
+
// --- Harness version (read once at load time) --------------------------------
|
|
864
|
+
const HARNESS_VERSION = (() => {
|
|
865
|
+
const pkgPath = join(__dirname, "package.json");
|
|
873
866
|
try {
|
|
874
867
|
if (existsSync(pkgPath)) {
|
|
875
868
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
876
|
-
|
|
869
|
+
return pkg.version ?? "?.?.?";
|
|
877
870
|
}
|
|
878
871
|
} catch { /* ignore */ }
|
|
879
|
-
|
|
872
|
+
return "?.?.?";
|
|
873
|
+
})();
|
|
874
|
+
|
|
875
|
+
function printBanner(): void {
|
|
876
|
+
console.error(`[Harness] v${HARNESS_VERSION}`);
|
|
880
877
|
}
|
|
881
878
|
|
|
882
879
|
function ensureHarnessDir() {
|
|
@@ -2322,8 +2319,41 @@ Run \`bd ready\` to see current bd issues.
|
|
|
2322
2319
|
},
|
|
2323
2320
|
});
|
|
2324
2321
|
|
|
2322
|
+
// --- /harness-header — Toggle harness custom header vs built-in Pi header ----
|
|
2323
|
+
pi.registerCommand("harness-header", {
|
|
2324
|
+
description: "Toggle or restore header: /harness-header [harness|builtin]",
|
|
2325
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
2326
|
+
if (ctx.mode !== "tui") {
|
|
2327
|
+
ctx.ui.notify("Header control is only available in TUI mode.", "info");
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
const mode = args.trim().toLowerCase();
|
|
2332
|
+
if (mode === "builtin" || mode === "pi") {
|
|
2333
|
+
ctx.ui.setHeader(undefined);
|
|
2334
|
+
ctx.ui.notify("Built-in Pi header restored.", "info");
|
|
2335
|
+
} else if (mode === "harness" || mode === "" || mode === "") {
|
|
2336
|
+
const { createHarnessHeader } = await import("./packages/tui/src/harness-header.js");
|
|
2337
|
+
ctx.ui.setHeader((tui, theme) =>
|
|
2338
|
+
createHarnessHeader(tui, theme, {
|
|
2339
|
+
version: HARNESS_VERSION,
|
|
2340
|
+
productName: "Harness",
|
|
2341
|
+
}),
|
|
2342
|
+
);
|
|
2343
|
+
ctx.ui.notify("Harness custom header installed.", "info");
|
|
2344
|
+
} else {
|
|
2345
|
+
ctx.ui.notify(
|
|
2346
|
+
"Usage: /harness-header [harness|builtin]\n" +
|
|
2347
|
+
" harness — install the Harness half-block logo header (default)\n" +
|
|
2348
|
+
" builtin — restore Pi's built-in header",
|
|
2349
|
+
"info",
|
|
2350
|
+
);
|
|
2351
|
+
}
|
|
2352
|
+
},
|
|
2353
|
+
});
|
|
2354
|
+
|
|
2325
2355
|
// --- Footer status (persistent badge) --------------------------------
|
|
2326
|
-
pi.on("session_start", (_event, ctx) => {
|
|
2356
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
2327
2357
|
// Capture only the setStatus function, not the ctx
|
|
2328
2358
|
footerSetStatus = ctx.ui.setStatus.bind(ctx.ui);
|
|
2329
2359
|
refreshFooterStatus(
|
|
@@ -2333,6 +2363,27 @@ Run \`bd ready\` to see current bd issues.
|
|
|
2333
2363
|
hasCookieSource,
|
|
2334
2364
|
() => lastActiveProvider,
|
|
2335
2365
|
);
|
|
2366
|
+
|
|
2367
|
+
// --- Install Harness custom header ----------------------------------
|
|
2368
|
+
// Replace Pi's built-in header with harness-branded half-block logo.
|
|
2369
|
+
// Ctrl+O expansion works via setExpanded() on the component.
|
|
2370
|
+
if (ctx.mode === "tui") {
|
|
2371
|
+
const { createHarnessHeader } = await import("./packages/tui/src/harness-header.js");
|
|
2372
|
+
ctx.ui.setHeader((tui, theme) =>
|
|
2373
|
+
createHarnessHeader(tui, theme, {
|
|
2374
|
+
version: HARNESS_VERSION,
|
|
2375
|
+
productName: "Harness",
|
|
2376
|
+
}),
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
// --- Show collected startup messages --------------------------------
|
|
2381
|
+
// These messages were collected during extension load but console.error
|
|
2382
|
+
// was suppressed by pi.dev 1.0.0. Show them via ui.notify now.
|
|
2383
|
+
if (startupMessages.length > 0) {
|
|
2384
|
+
const header = `Harness v${HARNESS_VERSION} startup status:`;
|
|
2385
|
+
ctx.ui.notify([header, ...startupMessages].join("\n"), "info");
|
|
2386
|
+
}
|
|
2336
2387
|
});
|
|
2337
2388
|
|
|
2338
2389
|
pi.on("turn_end", (_event, ctx) => {
|
|
@@ -2532,8 +2583,10 @@ function refreshFooterStatus(
|
|
|
2532
2583
|
// mirror ? JSON.stringify(mirror) : null,
|
|
2533
2584
|
// );
|
|
2534
2585
|
const freshness = mirrorStore.freshness(mirror, nowMs);
|
|
2586
|
+
const statusValue = buildFooterStatusValue(local, mirror, freshness, hasCookieSource(), provider);
|
|
2587
|
+
// Prepend harness version so it shows in the footer during startup
|
|
2535
2588
|
setStatus(
|
|
2536
2589
|
"harness-runtime",
|
|
2537
|
-
|
|
2590
|
+
`[Harness ${HARNESS_VERSION}] ${statusValue}`,
|
|
2538
2591
|
);
|
|
2539
2592
|
}
|
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.135",
|
|
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",
|