pi-harness-runtime 1.1.458 → 1.1.459
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 +35 -0
- package/README.md +10 -2
- package/harness/honcho-init.ts +907 -192
- package/harness/honcho-memory.ts +31 -69
- package/harness/key-file-audit.ts +79 -1
- package/harness/service-commands.ts +48 -16
- package/index.ts +244 -48
- package/package.json +3 -8
- package/packages/agent-policy/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/evaluation-engine/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/file-copy-helper/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/logging/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/prompt-compiler/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/relay/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/tooling-preference/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/two-phase-review/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/package.json +1 -1
- package/packages/write-review/package.json +1 -1
package/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
formatKeyFileFixes,
|
|
27
27
|
formatKeyPermissionFixes,
|
|
28
28
|
selectKeyFileFixes,
|
|
29
|
+
secureKeyTree,
|
|
29
30
|
type KeyFileAuditResult,
|
|
30
31
|
} from "./harness/key-file-audit.ts";
|
|
31
32
|
import { renderDetailLines } from "./harness/startup-lines.ts";
|
|
@@ -42,6 +43,12 @@ import {
|
|
|
42
43
|
} from "./harness/startup-report.ts";
|
|
43
44
|
import { localSkillsReport, skillsReport } from "./harness/skills-startup.ts";
|
|
44
45
|
import { isChannelDisabled, setChannelDisabled } from "./harness/notification-settings.ts";
|
|
46
|
+
// The Honcho contract lives with the Honcho integration. A type-only import
|
|
47
|
+
// is erased at runtime, so the startup keeps loading the module lazily.
|
|
48
|
+
import type {
|
|
49
|
+
HonchoInitResult,
|
|
50
|
+
HonchoMcpRegistrar,
|
|
51
|
+
} from "./harness/honcho-init.ts";
|
|
45
52
|
import { UsageTracker } from "./tracker.ts";
|
|
46
53
|
import { MirrorStore, type MirrorRecord } from "./mirror.ts";
|
|
47
54
|
import { MiniMaxQuotaScraper } from "./harness/e2e/minimax-quota-scraper.js";
|
|
@@ -211,17 +218,44 @@ function getKeyFileAudit(): KeyFileAuditResult | null {
|
|
|
211
218
|
* is a list nobody runs. The command is never executed here.
|
|
212
219
|
*/
|
|
213
220
|
function reportExposedKeyFiles(): void {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
let audit = getKeyFileAudit();
|
|
222
|
+
let exposed = audit?.exposed ?? [];
|
|
223
|
+
let exposedDirectories = audit?.exposedDirectories ?? [];
|
|
217
224
|
if (exposed.length === 0 && exposedDirectories.length === 0) return;
|
|
225
|
+
|
|
226
|
+
// Key files belong to this app and are private by design. Repair unsafe
|
|
227
|
+
// Unix permissions automatically; keep the actionable warning only when
|
|
228
|
+
// the platform cannot express the repair or a path cannot be changed.
|
|
229
|
+
const repair = secureKeyTree(harnessKeysDir());
|
|
230
|
+
if (repair.supported) {
|
|
231
|
+
try {
|
|
232
|
+
audit = auditKeyFiles({ keysDir: harnessKeysDir() });
|
|
233
|
+
keyFileAudit = audit;
|
|
234
|
+
} catch {
|
|
235
|
+
// Preserve the original findings if the verification scan fails.
|
|
236
|
+
}
|
|
237
|
+
exposed = audit?.exposed ?? exposed;
|
|
238
|
+
exposedDirectories = audit?.exposedDirectories ?? exposedDirectories;
|
|
239
|
+
if (exposed.length === 0 && exposedDirectories.length === 0) {
|
|
240
|
+
addHarnessMessage(
|
|
241
|
+
"Keys",
|
|
242
|
+
`permissions secured automatically (${repair.securedFiles} files, ${repair.securedDirectories} directories)`,
|
|
243
|
+
"ok",
|
|
244
|
+
);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
218
249
|
const report = exposedKeyFilesReport({
|
|
219
250
|
exposed,
|
|
220
251
|
exposedDirectories,
|
|
221
252
|
fixes: formatKeyPermissionFixes({ keysDir: harnessKeysDir() }),
|
|
222
253
|
});
|
|
223
254
|
if (!report) return;
|
|
224
|
-
|
|
255
|
+
const failedPaths = repair.failedPaths.length > 0
|
|
256
|
+
? [`Could not change permissions for: ${repair.failedPaths.join(", ")}`]
|
|
257
|
+
: [];
|
|
258
|
+
addHarnessMessage(report.label, report.text, report.status, [...failedPaths, ...report.details]);
|
|
225
259
|
}
|
|
226
260
|
|
|
227
261
|
/**
|
|
@@ -3220,39 +3254,65 @@ function initConsoleGuard(pi: ExtensionAPI): void {
|
|
|
3220
3254
|
}
|
|
3221
3255
|
|
|
3222
3256
|
// --- honcho-memory: Honcho MCP for peer/user memory via https://mcp.honcho.dev ------
|
|
3223
|
-
// Registers Honcho MCP server
|
|
3257
|
+
// Registers the Honcho MCP server with Pi's NATIVE MCP support and implements
|
|
3258
|
+
// the automatic memory lifecycle:
|
|
3224
3259
|
// - Ingest sanitized messages on completed turns
|
|
3225
3260
|
// - Retrieve relevant context before agent execution
|
|
3226
3261
|
// - Deduplication by message ID
|
|
3227
3262
|
// - Bounded context injection with provenance
|
|
3228
3263
|
|
|
3264
|
+
/**
|
|
3265
|
+
* The contract of the Honcho integration module.
|
|
3266
|
+
*
|
|
3267
|
+
* The module is loaded at runtime, so the shape of its exports is declared
|
|
3268
|
+
* here: this is the only part TypeScript cannot check for us.
|
|
3269
|
+
*/
|
|
3270
|
+
interface HonchoModule {
|
|
3271
|
+
initHoncho: (options: {
|
|
3272
|
+
apiKey?: string;
|
|
3273
|
+
pi?: HonchoMcpRegistrar;
|
|
3274
|
+
}) => Promise<HonchoInitResult>;
|
|
3275
|
+
registerHonchoLifecycle: (pi: unknown) => void;
|
|
3276
|
+
/** The credential: the environment wins over the key file. */
|
|
3277
|
+
loadHonchoApiKey: () => string | undefined;
|
|
3278
|
+
/** Removes the credential from a text. */
|
|
3279
|
+
redactHonchoKey: (text: string, apiKey: string) => string;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3229
3282
|
async function initHoncho(pi: ExtensionAPI): Promise<void> {
|
|
3230
3283
|
addHarnessMessage("Honcho", "initializing", "wait");
|
|
3284
|
+
let apiKey = "";
|
|
3285
|
+
let honcho: HonchoModule | null = null;
|
|
3231
3286
|
try {
|
|
3232
|
-
// Import
|
|
3233
|
-
|
|
3287
|
+
// Import the Honcho integration module.
|
|
3288
|
+
honcho = (await import("./harness/honcho-init.js")) as unknown as HonchoModule;
|
|
3234
3289
|
|
|
3235
|
-
//
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3290
|
+
// The credential comes from the loader of the module: the environment
|
|
3291
|
+
// variable wins over the key file, and the file is the per-user default.
|
|
3292
|
+
apiKey = honcho.loadHonchoApiKey() ?? "";
|
|
3293
|
+
if (!apiKey) {
|
|
3294
|
+
// A key file that exists but is empty is a different advice than a
|
|
3295
|
+
// missing file.
|
|
3296
|
+
const { readFileSync, existsSync } = await import("node:fs");
|
|
3297
|
+
const home = process.env.HOME || process.env.USERPROFILE || homedir();
|
|
3298
|
+
const keyPath = `${home}/.pi-harness-runtime/keys/honcho-api-key.txt`;
|
|
3299
|
+
const emptyFile = existsSync(keyPath) && readFileSync(keyPath, "utf8").trim() === "";
|
|
3300
|
+
|
|
3301
|
+
if (emptyFile) {
|
|
3302
|
+
logStartup("[pi-harness] Honcho: API key is empty — skipping");
|
|
3303
|
+
addHarnessMessage("Honcho", "API key empty", "warn", [
|
|
3304
|
+
...keyFileFixesOrFallback("Honcho", ["API key"]),
|
|
3305
|
+
"Then reload Pi.",
|
|
3306
|
+
]);
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3239
3309
|
|
|
3240
|
-
if (!existsSync(keyPath)) {
|
|
3241
3310
|
logStartup("[pi-harness] Honcho not configured:");
|
|
3242
3311
|
logStartup("[pi-harness] Get key: https://app.honcho.dev/api-keys");
|
|
3243
3312
|
logStartup(`[pi-harness] Then: echo "{api-key}" > ~/.pi-harness-runtime/keys/honcho-api-key.txt`);
|
|
3244
3313
|
addHarnessMessage("Honcho", "API key missing", "warn", [
|
|
3245
3314
|
...keyFileFixesOrFallback("Honcho", ["API key"]),
|
|
3246
|
-
"
|
|
3247
|
-
]);
|
|
3248
|
-
return;
|
|
3249
|
-
}
|
|
3250
|
-
|
|
3251
|
-
const apiKey = readFileSync(keyPath, "utf8").trim();
|
|
3252
|
-
if (!apiKey) {
|
|
3253
|
-
logStartup("[pi-harness] Honcho: API key is empty — skipping");
|
|
3254
|
-
addHarnessMessage("Honcho", "API key empty", "warn", [
|
|
3255
|
-
...keyFileFixesOrFallback("Honcho", ["API key"]),
|
|
3315
|
+
"Get a key: https://app.honcho.dev/api-keys",
|
|
3256
3316
|
"Then reload Pi.",
|
|
3257
3317
|
]);
|
|
3258
3318
|
return;
|
|
@@ -3260,27 +3320,130 @@ async function initHoncho(pi: ExtensionAPI): Promise<void> {
|
|
|
3260
3320
|
|
|
3261
3321
|
// Register lifecycle hooks using the new integration
|
|
3262
3322
|
// SAFETY: pi.on accepts these event names at runtime
|
|
3263
|
-
registerHonchoLifecycle(pi as unknown as { on: (event: string, handler: (...args: unknown[]) => void | Promise<void>) => void });
|
|
3264
|
-
|
|
3265
|
-
// Initialize Honcho with the API key
|
|
3266
|
-
//
|
|
3267
|
-
|
|
3323
|
+
honcho.registerHonchoLifecycle(pi as unknown as { on: (event: string, handler: (...args: unknown[]) => void | Promise<void>) => void });
|
|
3324
|
+
|
|
3325
|
+
// Initialize Honcho with the API key. The integration uses Pi's own MCP
|
|
3326
|
+
// client, so no event adapter is passed any more. It also registers
|
|
3327
|
+
// the MCP server with the extension API of Pi, so the model and
|
|
3328
|
+
// `/mcp` see it - and a refused registration is not fatal: the
|
|
3329
|
+
// harness talks to the server through its own MCP client, so only
|
|
3330
|
+
// the native tools are missing and the rest of the startup continues.
|
|
3331
|
+
// SAFETY: the runtime that runs this extension exposes
|
|
3332
|
+
// registerMcpServer (verified with Pi 1.4.0); the local type
|
|
3333
|
+
// definitions are older, so the call is cast.
|
|
3334
|
+
const result = await honcho.initHoncho({
|
|
3335
|
+
apiKey,
|
|
3336
|
+
pi: pi as unknown as HonchoMcpRegistrar,
|
|
3337
|
+
});
|
|
3268
3338
|
|
|
3269
|
-
if (result) {
|
|
3270
|
-
logStartup("[pi-harness] Honcho
|
|
3271
|
-
addHarnessMessage("Honcho", "
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
"How to fix: Check HONCHO_API_KEY in ~/.pi-harness-runtime/keys/honcho-api-key.txt",
|
|
3276
|
-
"Verify Honcho account is active at honcho.dev.",
|
|
3339
|
+
if (!result || !result.status) {
|
|
3340
|
+
logStartup("[pi-harness] Honcho: initialization produced no status");
|
|
3341
|
+
addHarnessMessage("Honcho", "init failed", "err", [
|
|
3342
|
+
"Check /tmp/pi-harness.log for the Honcho reason.",
|
|
3343
|
+
"The Honcho integration returned no status.",
|
|
3344
|
+
"Honcho memory stays disabled for this session.",
|
|
3277
3345
|
]);
|
|
3346
|
+
return;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
switch (result.status) {
|
|
3350
|
+
case "ready": {
|
|
3351
|
+
logStartup("[pi-harness] Honcho integration ready");
|
|
3352
|
+
if (result.mcpRegistered) {
|
|
3353
|
+
logStartup("[pi-harness] Honcho: native MCP server registered");
|
|
3354
|
+
addHarnessMessage("Honcho", "initialized", "ok");
|
|
3355
|
+
} else {
|
|
3356
|
+
// The memory works, but the model has no Honcho tools: the
|
|
3357
|
+
// user has to know that, not only the log. The reason of
|
|
3358
|
+
// the registration names the cause, so the advice is not
|
|
3359
|
+
// always "check the Pi version".
|
|
3360
|
+
const cause = honcho.redactHonchoKey(
|
|
3361
|
+
result.mcpRegistrationReason ?? "the reason was not reported",
|
|
3362
|
+
apiKey,
|
|
3363
|
+
);
|
|
3364
|
+
logStartup(`[pi-harness] Honcho: native MCP server not registered (the model sees no Honcho tools): ${cause}`);
|
|
3365
|
+
// The advice follows the cause: a runtime without
|
|
3366
|
+
// registerMcpServer is a different problem than a name
|
|
3367
|
+
// that another extension owns.
|
|
3368
|
+
const capability = cause.includes("registerMcpServer")
|
|
3369
|
+
? "This runtime does not provide registerMcpServer: the Honcho memory works, but the model sees no Honcho tools."
|
|
3370
|
+
: "The Honcho memory works, but the model sees no Honcho tools.";
|
|
3371
|
+
addHarnessMessage("Honcho", "native MCP tools not registered", "warn", [
|
|
3372
|
+
`The registration failed: ${cause}`,
|
|
3373
|
+
"Check /tmp/pi-harness.log for the Honcho reason.",
|
|
3374
|
+
capability,
|
|
3375
|
+
]);
|
|
3376
|
+
}
|
|
3377
|
+
break;
|
|
3378
|
+
}
|
|
3379
|
+
case "missing_key": {
|
|
3380
|
+
// The only state that may point at the key file: the credential
|
|
3381
|
+
// is what is missing.
|
|
3382
|
+
logStartup("[pi-harness] Honcho not configured:");
|
|
3383
|
+
logStartup("[pi-harness] Get key: https://app.honcho.dev/api-keys");
|
|
3384
|
+
logStartup(`[pi-harness] Then: echo "{api-key}" > ~/.pi-harness-runtime/keys/honcho-api-key.txt`);
|
|
3385
|
+
addHarnessMessage("Honcho", "API key missing", "warn", [
|
|
3386
|
+
...keyFileFixesOrFallback("Honcho", ["API key"]),
|
|
3387
|
+
"Get a key: https://app.honcho.dev/api-keys",
|
|
3388
|
+
"Then reload Pi.",
|
|
3389
|
+
]);
|
|
3390
|
+
break;
|
|
3391
|
+
}
|
|
3392
|
+
case "mcp_unavailable": {
|
|
3393
|
+
// The key was read successfully - the problem is the MCP runtime.
|
|
3394
|
+
const reason = honcho.redactHonchoKey(result.reason ?? "no reason given", apiKey);
|
|
3395
|
+
const hint = honcho.redactHonchoKey(
|
|
3396
|
+
result.hint ?? "The native MCP client library @earendil-works/pi-mcp is required.",
|
|
3397
|
+
apiKey,
|
|
3398
|
+
);
|
|
3399
|
+
logStartup(`[pi-harness] Honcho: native MCP unavailable (${reason})`);
|
|
3400
|
+
addHarnessMessage("Honcho", "native MCP unavailable", "err", [
|
|
3401
|
+
"Check /tmp/pi-harness.log for the Honcho reason.",
|
|
3402
|
+
reason,
|
|
3403
|
+
hint,
|
|
3404
|
+
]);
|
|
3405
|
+
break;
|
|
3406
|
+
}
|
|
3407
|
+
case "registration_rejected": {
|
|
3408
|
+
const reason = honcho.redactHonchoKey(
|
|
3409
|
+
result.reason ?? "the server did not accept the request",
|
|
3410
|
+
apiKey,
|
|
3411
|
+
);
|
|
3412
|
+
const httpStatus = typeof result.httpStatus === "number" ? ` (HTTP ${result.httpStatus})` : "";
|
|
3413
|
+
const hint = honcho.redactHonchoKey(
|
|
3414
|
+
result.hint ?? "Check the Honcho account at https://honcho.dev.",
|
|
3415
|
+
apiKey,
|
|
3416
|
+
);
|
|
3417
|
+
logStartup(`[pi-harness] Honcho: the server refused the request${httpStatus} (the MCP server is not registered): ${reason}`);
|
|
3418
|
+
addHarnessMessage("Honcho", "server refused the request", "err", [
|
|
3419
|
+
"Check the Honcho account and the endpoint: https://app.honcho.dev/api-keys",
|
|
3420
|
+
reason,
|
|
3421
|
+
hint,
|
|
3422
|
+
]);
|
|
3423
|
+
break;
|
|
3424
|
+
}
|
|
3425
|
+
default: {
|
|
3426
|
+
const reason = honcho.redactHonchoKey(String(result.status), apiKey);
|
|
3427
|
+
logStartup("[pi-harness] Honcho: initialization failed:", reason);
|
|
3428
|
+
addHarnessMessage("Honcho", "init failed", "err", [
|
|
3429
|
+
"Check /tmp/pi-harness.log for the Honcho reason.",
|
|
3430
|
+
reason,
|
|
3431
|
+
"Honcho memory stays disabled for this session.",
|
|
3432
|
+
]);
|
|
3433
|
+
break;
|
|
3434
|
+
}
|
|
3278
3435
|
}
|
|
3279
3436
|
} catch (err) {
|
|
3280
|
-
|
|
3437
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3438
|
+
const reason =
|
|
3439
|
+
honcho && typeof honcho.redactHonchoKey === "function"
|
|
3440
|
+
? honcho.redactHonchoKey(message, apiKey)
|
|
3441
|
+
: message;
|
|
3442
|
+
logStartup("[pi-harness] Honcho: init failed:", reason);
|
|
3281
3443
|
addHarnessMessage("Honcho", "init failed", "err", [
|
|
3282
|
-
|
|
3283
|
-
|
|
3444
|
+
"Check /tmp/pi-harness.log for the Honcho reason.",
|
|
3445
|
+
reason,
|
|
3446
|
+
"Honcho memory stays disabled for this session.",
|
|
3284
3447
|
]);
|
|
3285
3448
|
}
|
|
3286
3449
|
}
|
|
@@ -3820,8 +3983,31 @@ async function initHermesSkills(pi: ExtensionAPI): Promise<void> {
|
|
|
3820
3983
|
addHarnessMessage("Skills", "initializing", "wait");
|
|
3821
3984
|
try {
|
|
3822
3985
|
// Dynamically import to avoid circular deps
|
|
3823
|
-
const { initSkills, sanitizationStatus } =
|
|
3986
|
+
const { initSkills, sanitizationStatus, sanitizationFilePath } =
|
|
3824
3987
|
await import("./packages/skills/dist/index.js");
|
|
3988
|
+
let sanitizationFileCreated = false;
|
|
3989
|
+
let sanitizationFileCreateError: string | undefined;
|
|
3990
|
+
try {
|
|
3991
|
+
const path = sanitizationFilePath();
|
|
3992
|
+
const { existsSync, mkdirSync, writeFileSync } = await import("node:fs");
|
|
3993
|
+
const { dirname } = await import("node:path");
|
|
3994
|
+
if (!existsSync(path)) {
|
|
3995
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
3996
|
+
try {
|
|
3997
|
+
writeFileSync(
|
|
3998
|
+
path,
|
|
3999
|
+
`${JSON.stringify({ rules: [], nameMap: {} }, null, 2)}\n`,
|
|
4000
|
+
{ encoding: "utf8", flag: "wx", mode: 0o600 },
|
|
4001
|
+
);
|
|
4002
|
+
sanitizationFileCreated = true;
|
|
4003
|
+
} catch (error) {
|
|
4004
|
+
// Another Pi process may have created the file after existsSync.
|
|
4005
|
+
if ((error as NodeJS.ErrnoException)?.code !== "EEXIST") throw error;
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
} catch (error) {
|
|
4009
|
+
sanitizationFileCreateError = error instanceof Error ? error.message : String(error);
|
|
4010
|
+
}
|
|
3825
4011
|
|
|
3826
4012
|
// Scan skills from default locations
|
|
3827
4013
|
const result = initSkills();
|
|
@@ -3833,21 +4019,30 @@ async function initHermesSkills(pi: ExtensionAPI): Promise<void> {
|
|
|
3833
4019
|
const local = localSkillsReport(localCount);
|
|
3834
4020
|
addHarnessMessage("Skills", local.text, local.status, local.details);
|
|
3835
4021
|
// The rules that keep a client name out of the shared collection
|
|
3836
|
-
// live in a local file
|
|
3837
|
-
//
|
|
3838
|
-
// name travels into the collection. That is a visible state, not
|
|
3839
|
-
// a silent one.
|
|
4022
|
+
// live in a local file. Create a private empty template on first
|
|
4023
|
+
// use; client-specific rules can be added locally.
|
|
3840
4024
|
try {
|
|
3841
4025
|
const rules = sanitizationStatus();
|
|
3842
|
-
if (
|
|
4026
|
+
if (sanitizationFileCreated && rules.configured) {
|
|
4027
|
+
addHarnessMessage(
|
|
4028
|
+
"Skill privacy",
|
|
4029
|
+
"created a private sanitization rules file",
|
|
4030
|
+
"info",
|
|
4031
|
+
[
|
|
4032
|
+
`File: ${rules.path}`,
|
|
4033
|
+
"The file starts with no client-specific rules. Add private rules before publishing skills that contain client names.",
|
|
4034
|
+
],
|
|
4035
|
+
);
|
|
4036
|
+
} else if (!rules.configured) {
|
|
3843
4037
|
addHarnessMessage(
|
|
3844
4038
|
"Skill privacy",
|
|
3845
|
-
"sanitization rules not
|
|
4039
|
+
"sanitization rules file could not be created",
|
|
3846
4040
|
"warn",
|
|
3847
4041
|
[
|
|
3848
|
-
`
|
|
3849
|
-
"
|
|
3850
|
-
"
|
|
4042
|
+
`Create ${rules.path} with { "rules": [], "nameMap": {} } and add private client-specific rules if needed.`,
|
|
4043
|
+
"Check the path in PI_SKILL_SANITIZATION_FILE.",
|
|
4044
|
+
"PI_SKILL_SANITIZATION_FILE must name a file path, not a JSON array.",
|
|
4045
|
+
...(sanitizationFileCreateError ? [sanitizationFileCreateError] : []),
|
|
3851
4046
|
...(rules.error ? [rules.error] : []),
|
|
3852
4047
|
],
|
|
3853
4048
|
);
|
|
@@ -6020,6 +6215,7 @@ Run \`bd ready\` to see current bd issues.
|
|
|
6020
6215
|
// --- /usage today — focused view -------------------------------------
|
|
6021
6216
|
pi.registerCommand("usage-today", {
|
|
6022
6217
|
description: "Show today's usage + 5h window",
|
|
6218
|
+
// The handler returns a Promise: the command API of Pi requires one.
|
|
6023
6219
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
6024
6220
|
const local = aggregateWindows(tracker.all());
|
|
6025
6221
|
const lines = [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-harness-runtime",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.459",
|
|
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": {
|
|
@@ -199,8 +199,7 @@
|
|
|
199
199
|
"@earendil-works/pi-ai": "^1.3.0",
|
|
200
200
|
"@earendil-works/pi-coding-agent": "*",
|
|
201
201
|
"@earendil-works/pi-tui": "*",
|
|
202
|
-
"typebox": "*"
|
|
203
|
-
"pi-mcp-adapter": ">=6.0.0"
|
|
202
|
+
"typebox": "*"
|
|
204
203
|
},
|
|
205
204
|
"devDependencies": {
|
|
206
205
|
"@biomejs/biome": "^2.4.7",
|
|
@@ -224,6 +223,7 @@
|
|
|
224
223
|
"@aws-sdk/s3-request-presigner": "^3.1152.0",
|
|
225
224
|
"@earendil-works/chord": "^1.3.0",
|
|
226
225
|
"@earendil-works/pi-durable": "^1.3.0",
|
|
226
|
+
"@earendil-works/pi-mcp": "^1.4.0",
|
|
227
227
|
"@langchain/core": "^1.2.9",
|
|
228
228
|
"@langchain/langgraph": "^1.4.13",
|
|
229
229
|
"@langchain/langgraph-checkpoint": "^1.1.5",
|
|
@@ -237,10 +237,5 @@
|
|
|
237
237
|
"ws": "^8.22.0",
|
|
238
238
|
"yaml": "^2.5.0",
|
|
239
239
|
"zod": "^4.6.7"
|
|
240
|
-
},
|
|
241
|
-
"peerDependenciesMeta": {
|
|
242
|
-
"pi-mcp-adapter": {
|
|
243
|
-
"optional": true
|
|
244
|
-
}
|
|
245
240
|
}
|
|
246
241
|
}
|