portable-agent-layer 0.61.3 → 0.62.0
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/assets/schema/pal-settings.schema.json +111 -0
- package/assets/skills/opinion/SKILL.md +7 -7
- package/assets/skills/opinion/tools/opinion.ts +6 -4
- package/assets/templates/hooks.copilot.json +4 -0
- package/assets/templates/hooks.cursor.json +4 -0
- package/assets/templates/pal-settings.json +8 -3
- package/assets/templates/settings.claude.json +9 -2
- package/package.json +1 -1
- package/src/cli/index.ts +16 -1
- package/src/hooks/RtkWrap.ts +52 -0
- package/src/hooks/UserPromptOrchestrator.ts +3 -3
- package/src/hooks/handlers/failure-principle.ts +1 -1
- package/src/hooks/handlers/inject-retrieval.ts +18 -6
- package/src/hooks/handlers/rating.ts +1 -1
- package/src/hooks/handlers/session-intelligence.ts +1 -1
- package/src/hooks/handlers/session-name.ts +1 -1
- package/src/hooks/handlers/update-check.ts +8 -5
- package/src/hooks/lib/inference.ts +2 -41
- package/src/hooks/lib/opinions.ts +15 -4
- package/src/hooks/lib/settings.ts +5 -0
- package/src/hooks/lib/steering.ts +162 -0
- package/src/hooks/lib/text-similarity.ts +18 -0
- package/src/hooks/lib/which.ts +41 -0
- package/src/targets/lib.ts +18 -1
- package/src/targets/opencode/plugin.ts +35 -4
- package/src/tools/agent/algorithm-reflect.ts +2 -1
- package/src/tools/agent/handoff-note.ts +3 -2
- package/src/tools/agent/project.ts +42 -2
- package/src/tools/agent/relationship-note.ts +6 -11
- package/src/tools/agent/thread.ts +6 -9
- package/src/tools/agent/wisdom-frame.ts +2 -1
- package/src/tools/lib/emit.ts +31 -0
- package/src/tools/relationship-reflect.ts +14 -13
- package/src/tools/token-cost.ts +49 -0
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "../hooks/lib/opinions";
|
|
27
27
|
import { palHome } from "../hooks/lib/paths";
|
|
28
28
|
import { similarity } from "../hooks/lib/text-similarity";
|
|
29
|
+
import { emit } from "./lib/emit";
|
|
29
30
|
|
|
30
31
|
// ── Types ──
|
|
31
32
|
|
|
@@ -413,11 +414,11 @@ Output:
|
|
|
413
414
|
const notes = loadNotes(daysBack);
|
|
414
415
|
const ratings = loadRatings(daysBack);
|
|
415
416
|
|
|
416
|
-
|
|
417
|
-
|
|
417
|
+
emit.ok(`Loaded ${notes.length} notes from last ${daysBack} days`);
|
|
418
|
+
emit.ok(`Loaded ${ratings.length} ratings`);
|
|
418
419
|
|
|
419
420
|
if (notes.length === 0 && ratings.length === 0) {
|
|
420
|
-
|
|
421
|
+
emit.ok("No data to analyze");
|
|
421
422
|
process.exit(0);
|
|
422
423
|
}
|
|
423
424
|
|
|
@@ -425,42 +426,42 @@ Output:
|
|
|
425
426
|
|
|
426
427
|
const avgRating =
|
|
427
428
|
ratings.length > 0 ? ratings.reduce((s, r) => s + r.rating, 0) / ratings.length : 0;
|
|
428
|
-
|
|
429
|
+
emit.ok(`\nAverage Rating: ${avgRating.toFixed(1)}/10`);
|
|
429
430
|
|
|
430
431
|
const summaries = groupNoteOccurrences(notes);
|
|
431
|
-
|
|
432
|
+
emit.ok(`Observations: ${summaries.length} unique`);
|
|
432
433
|
|
|
433
434
|
if (opinionChanges.length > 0) {
|
|
434
|
-
|
|
435
|
+
emit.ok("\nOpinion changes:");
|
|
435
436
|
for (const change of opinionChanges) {
|
|
436
437
|
if (change.action === "created") {
|
|
437
|
-
|
|
438
|
+
emit.ok(
|
|
438
439
|
` + NEW (${Math.round(change.newConfidence * 100)}%) ${change.statement.slice(0, 80)}`
|
|
439
440
|
);
|
|
440
441
|
} else {
|
|
441
|
-
|
|
442
|
+
emit.ok(
|
|
442
443
|
` ~ ${Math.round(change.oldConfidence ?? 0 * 100)}% → ${Math.round(change.newConfidence * 100)}% ${change.statement.slice(0, 80)}`
|
|
443
444
|
);
|
|
444
445
|
}
|
|
445
446
|
}
|
|
446
447
|
} else {
|
|
447
|
-
|
|
448
|
+
emit.ok("\nNo opinion changes");
|
|
448
449
|
}
|
|
449
450
|
|
|
450
451
|
if (dryRun) {
|
|
451
|
-
|
|
452
|
+
emit.data("[DRY RUN] Would write reflection report + update opinions");
|
|
452
453
|
} else {
|
|
453
454
|
const report = formatReport(period, notes, ratings, opinionChanges);
|
|
454
455
|
const filepath = writeReport(report, period);
|
|
455
456
|
setLastReflectDate(new Date().toISOString().slice(0, 10));
|
|
456
|
-
|
|
457
|
+
emit.ok(`\nCreated reflection report: ${filepath}`);
|
|
457
458
|
|
|
458
459
|
const opinions = readOpinions();
|
|
459
460
|
const high = opinions.filter((o) => o.confidence >= 0.85);
|
|
460
461
|
if (high.length > 0) {
|
|
461
|
-
|
|
462
|
+
emit.ok("\nHigh-confidence opinions (injected into context):");
|
|
462
463
|
for (const o of high) {
|
|
463
|
-
|
|
464
|
+
emit.ok(` [${Math.round(o.confidence * 100)}%] ${o.statement.slice(0, 80)}`);
|
|
464
465
|
}
|
|
465
466
|
}
|
|
466
467
|
}
|
package/src/tools/token-cost.ts
CHANGED
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
* Invoked via `pal cli usage [--today|--week|--month|--all] [--project <name>]`.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import { spawnSync } from "node:child_process";
|
|
11
12
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
12
13
|
import { homedir } from "node:os";
|
|
13
14
|
import { resolve } from "node:path";
|
|
14
15
|
import { parseArgs } from "node:util";
|
|
15
16
|
import { MODEL_PRICING } from "../hooks/lib/models";
|
|
16
17
|
import { palHome } from "../hooks/lib/paths";
|
|
18
|
+
import { findBinaryOnPath } from "../hooks/lib/which";
|
|
17
19
|
|
|
18
20
|
// ── Types ──
|
|
19
21
|
|
|
@@ -370,6 +372,51 @@ function readPalInference(): {
|
|
|
370
372
|
return { buckets, byModel, byCaller };
|
|
371
373
|
}
|
|
372
374
|
|
|
375
|
+
// ── rtk compression savings ──
|
|
376
|
+
|
|
377
|
+
interface RtkSummary {
|
|
378
|
+
total_commands: number;
|
|
379
|
+
total_saved: number;
|
|
380
|
+
avg_savings_pct: number;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Query rtk's own savings ledger. `installed: false` means rtk isn't on PATH;
|
|
385
|
+
* `summary: null` with `installed: true` means rtk is present but has no data
|
|
386
|
+
* (or errored) — the two cases print differently in the usage report.
|
|
387
|
+
*/
|
|
388
|
+
function readRtkGain(): { installed: boolean; summary: RtkSummary | null } {
|
|
389
|
+
const rtk = findBinaryOnPath("rtk");
|
|
390
|
+
if (!rtk) return { installed: false, summary: null };
|
|
391
|
+
try {
|
|
392
|
+
const r = spawnSync(rtk, ["gain", "--format", "json"], {
|
|
393
|
+
encoding: "utf8",
|
|
394
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
395
|
+
});
|
|
396
|
+
if (r.status !== 0 || !r.stdout) return { installed: true, summary: null };
|
|
397
|
+
const parsed = JSON.parse(r.stdout) as { summary?: RtkSummary };
|
|
398
|
+
return { installed: true, summary: parsed.summary ?? null };
|
|
399
|
+
} catch {
|
|
400
|
+
return { installed: true, summary: null };
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function printRtkGain(): void {
|
|
405
|
+
const { installed, summary } = readRtkGain();
|
|
406
|
+
console.log("\n rtk Compression\n");
|
|
407
|
+
if (!installed) {
|
|
408
|
+
console.log(" rtk not installed");
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (!summary || summary.total_commands === 0) {
|
|
412
|
+
console.log(" rtk installed — no savings recorded yet");
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
console.log(
|
|
416
|
+
` Tokens saved ${fmt(summary.total_saved).padStart(8)} tok ${summary.avg_savings_pct.toFixed(1)}% avg across ${fmt(summary.total_commands)} commands`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
373
420
|
// ── CLI ──
|
|
374
421
|
|
|
375
422
|
export function usage() {
|
|
@@ -426,6 +473,8 @@ export function usage() {
|
|
|
426
473
|
printRow("Total", tb.total);
|
|
427
474
|
}
|
|
428
475
|
|
|
476
|
+
printRtkGain();
|
|
477
|
+
|
|
429
478
|
const grand = emptyBucket();
|
|
430
479
|
for (const b of [cc.buckets.total, pal.buckets.total]) {
|
|
431
480
|
grand.input += b.input;
|