ultimate-pi 0.3.1 → 0.4.1
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/.agents/skills/harness-decisions/SKILL.md +37 -0
- package/.agents/skills/harness-governor/SKILL.md +1 -1
- package/.agents/skills/harness-orchestration/SKILL.md +54 -0
- package/.agents/skills/harness-plan/SKILL.md +4 -3
- package/.agents/skills/harness-sentrux-setup/SKILL.md +57 -0
- package/.agents/skills/scrapling-web/SKILL.md +93 -0
- package/.pi/PACKAGING.md +1 -0
- package/.pi/SYSTEM.md +13 -15
- package/.pi/agents/harness/adversary.md +3 -0
- package/.pi/agents/harness/evaluator.md +3 -0
- package/.pi/agents/harness/executor.md +4 -1
- package/.pi/agents/harness/meta-optimizer.md +2 -1
- package/.pi/agents/harness/planner.md +22 -1
- package/.pi/agents/harness/sentrux-bootstrap.md +42 -0
- package/.pi/agents/harness/tie-breaker.md +2 -0
- package/.pi/extensions/harness-ask-user.ts +74 -0
- package/.pi/extensions/harness-subagents.ts +9 -0
- package/.pi/extensions/lib/ask-user/dialog.ts +260 -0
- package/.pi/extensions/lib/ask-user/fallback.ts +78 -0
- package/.pi/extensions/lib/ask-user/render.ts +66 -0
- package/.pi/extensions/lib/ask-user/schema.ts +69 -0
- package/.pi/extensions/lib/ask-user/types.ts +41 -0
- package/.pi/extensions/lib/ask-user/validate-core.mjs +79 -0
- package/.pi/extensions/lib/ask-user/validate.ts +92 -0
- package/.pi/extensions/lib/harness-subagents/agent-loader.ts +126 -0
- package/.pi/extensions/lib/harness-subagents/agent-manifest.ts +119 -0
- package/.pi/extensions/lib/harness-subagents/agent-parser.ts +87 -0
- package/.pi/extensions/lib/harness-subagents/blackboard-tool.ts +118 -0
- package/.pi/extensions/lib/harness-subagents/blackboard.ts +175 -0
- package/.pi/extensions/lib/harness-subagents/spawn-policy.ts +27 -0
- package/.pi/extensions/lib/harness-subagents/types-blackboard.ts +27 -0
- package/.pi/extensions/lib/harness-subagents/vendored/agent-manager.ts +553 -0
- package/.pi/extensions/lib/harness-subagents/vendored/agent-runner.ts +637 -0
- package/.pi/extensions/lib/harness-subagents/vendored/agent-types.ts +175 -0
- package/.pi/extensions/lib/harness-subagents/vendored/context.ts +59 -0
- package/.pi/extensions/lib/harness-subagents/vendored/cross-extension-rpc.ts +134 -0
- package/.pi/extensions/lib/harness-subagents/vendored/custom-agents.ts +5 -0
- package/.pi/extensions/lib/harness-subagents/vendored/default-agents.ts +123 -0
- package/.pi/extensions/lib/harness-subagents/vendored/env.ts +43 -0
- package/.pi/extensions/lib/harness-subagents/vendored/group-join.ts +144 -0
- package/.pi/extensions/lib/harness-subagents/vendored/index.ts +2447 -0
- package/.pi/extensions/lib/harness-subagents/vendored/invocation-config.ts +52 -0
- package/.pi/extensions/lib/harness-subagents/vendored/memory.ts +182 -0
- package/.pi/extensions/lib/harness-subagents/vendored/model-resolver.ts +92 -0
- package/.pi/extensions/lib/harness-subagents/vendored/output-file.ts +115 -0
- package/.pi/extensions/lib/harness-subagents/vendored/prompts.ts +103 -0
- package/.pi/extensions/lib/harness-subagents/vendored/schedule-store.ts +177 -0
- package/.pi/extensions/lib/harness-subagents/vendored/schedule.ts +416 -0
- package/.pi/extensions/lib/harness-subagents/vendored/settings.ts +210 -0
- package/.pi/extensions/lib/harness-subagents/vendored/skill-loader.ts +108 -0
- package/.pi/extensions/lib/harness-subagents/vendored/types.ts +187 -0
- package/.pi/extensions/lib/harness-subagents/vendored/ui/agent-widget.ts +637 -0
- package/.pi/extensions/lib/harness-subagents/vendored/ui/conversation-viewer.ts +324 -0
- package/.pi/extensions/lib/harness-subagents/vendored/ui/schedule-menu.ts +110 -0
- package/.pi/extensions/lib/harness-subagents/vendored/usage.ts +71 -0
- package/.pi/extensions/lib/harness-subagents/vendored/worktree.ts +195 -0
- package/.pi/extensions/lib/harness-vcc-settings.ts +50 -0
- package/.pi/extensions/ultimate-pi-vcc.ts +17 -0
- package/.pi/harness/README.md +2 -1
- package/.pi/harness/agents.manifest.json +80 -0
- package/.pi/harness/docs/adrs/0009-sentrux-rules-lifecycle.md +9 -5
- package/.pi/harness/docs/adrs/0030-inhouse-vcc-compaction.md +40 -0
- package/.pi/harness/docs/adrs/README.md +1 -0
- package/.pi/harness/env.harness.template +28 -0
- package/.pi/harness/sentrux/architecture.manifest.json +6 -1
- package/.pi/prompts/harness-auto.md +2 -2
- package/.pi/prompts/harness-plan.md +2 -2
- package/.pi/prompts/harness-router-tune.md +2 -2
- package/.pi/prompts/harness-run.md +1 -0
- package/.pi/prompts/harness-setup.md +179 -340
- package/.pi/scripts/README.md +6 -1
- package/.pi/scripts/harness-agents-manifest.mjs +123 -0
- package/.pi/scripts/harness-cli-verify.sh +60 -11
- package/.pi/scripts/harness-generate-model-router.mjs +242 -0
- package/.pi/scripts/harness-graphify-bootstrap.sh +1 -6
- package/.pi/scripts/harness-resolve-up-pkg.mjs +71 -0
- package/.pi/scripts/harness-seed-project-contracts.mjs +33 -1
- package/.pi/scripts/harness-sentrux-bootstrap.mjs +146 -0
- package/.pi/scripts/harness-sync-env.mjs +148 -0
- package/.pi/scripts/harness-verify.mjs +19 -0
- package/.pi/scripts/harness-web-search.md +33 -0
- package/.pi/scripts/harness-web.py +177 -0
- package/.pi/scripts/harness_web/__init__.py +1 -0
- package/.pi/scripts/harness_web/config.py +80 -0
- package/.pi/scripts/harness_web/output.py +55 -0
- package/.pi/scripts/harness_web/scrape.py +120 -0
- package/.pi/scripts/harness_web/search_ddg.py +106 -0
- package/.pi/scripts/release.sh +338 -0
- package/.pi/scripts/sentrux-rules-sync.mjs +29 -7
- package/.pi/scripts/vendor-pi-vcc-settings.stub.ts +8 -0
- package/.pi/scripts/vendor-sync-pi-vcc.sh +40 -0
- package/.pi/settings.example.json +1 -7
- package/.sentrux/rules.toml +1 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +14 -0
- package/THIRD_PARTY_NOTICES.md +8 -0
- package/package.json +16 -12
- package/vendor/pi-vcc/README.md +215 -0
- package/vendor/pi-vcc/UPSTREAM_PIN.md +12 -0
- package/vendor/pi-vcc/demo.gif +0 -0
- package/vendor/pi-vcc/index.ts +12 -0
- package/vendor/pi-vcc/package.json +26 -0
- package/vendor/pi-vcc/scripts/audit-sessions.ts +88 -0
- package/vendor/pi-vcc/scripts/benchmark-real-sessions.ts +25 -0
- package/vendor/pi-vcc/scripts/compare-before-after.ts +36 -0
- package/vendor/pi-vcc/scripts/dump-branch-output.ts +20 -0
- package/vendor/pi-vcc/src/commands/pi-vcc.ts +36 -0
- package/vendor/pi-vcc/src/commands/vcc-recall.ts +65 -0
- package/vendor/pi-vcc/src/core/brief.ts +381 -0
- package/vendor/pi-vcc/src/core/build-sections.ts +79 -0
- package/vendor/pi-vcc/src/core/content.ts +60 -0
- package/vendor/pi-vcc/src/core/filter-noise.ts +42 -0
- package/vendor/pi-vcc/src/core/format-recall.ts +27 -0
- package/vendor/pi-vcc/src/core/format.ts +49 -0
- package/vendor/pi-vcc/src/core/lineage.ts +26 -0
- package/vendor/pi-vcc/src/core/load-messages.ts +41 -0
- package/vendor/pi-vcc/src/core/normalize.ts +66 -0
- package/vendor/pi-vcc/src/core/recall-scope.ts +14 -0
- package/vendor/pi-vcc/src/core/render-entries.ts +55 -0
- package/vendor/pi-vcc/src/core/report.ts +237 -0
- package/vendor/pi-vcc/src/core/sanitize.ts +5 -0
- package/vendor/pi-vcc/src/core/search-entries.ts +221 -0
- package/vendor/pi-vcc/src/core/settings.ts +8 -0
- package/vendor/pi-vcc/src/core/skill-collapse.ts +35 -0
- package/vendor/pi-vcc/src/core/summarize.ts +157 -0
- package/vendor/pi-vcc/src/core/tool-args.ts +14 -0
- package/vendor/pi-vcc/src/details.ts +7 -0
- package/vendor/pi-vcc/src/extract/commits.ts +69 -0
- package/vendor/pi-vcc/src/extract/files.ts +80 -0
- package/vendor/pi-vcc/src/extract/goals.ts +79 -0
- package/vendor/pi-vcc/src/extract/preferences.ts +55 -0
- package/vendor/pi-vcc/src/hooks/before-compact.ts +314 -0
- package/vendor/pi-vcc/src/sections.ts +12 -0
- package/vendor/pi-vcc/src/tools/recall.ts +109 -0
- package/vendor/pi-vcc/src/types.ts +14 -0
- package/vendor/pi-vcc/tests/before-compact-hook.test.ts +204 -0
- package/vendor/pi-vcc/tests/before-compact.test.ts +145 -0
- package/vendor/pi-vcc/tests/brief.test.ts +206 -0
- package/vendor/pi-vcc/tests/build-sections.test.ts +59 -0
- package/vendor/pi-vcc/tests/compile.test.ts +80 -0
- package/vendor/pi-vcc/tests/content.test.ts +31 -0
- package/vendor/pi-vcc/tests/extract-goals.test.ts +86 -0
- package/vendor/pi-vcc/tests/extract-preferences.test.ts +30 -0
- package/vendor/pi-vcc/tests/filter-noise.test.ts +61 -0
- package/vendor/pi-vcc/tests/fixtures.ts +61 -0
- package/vendor/pi-vcc/tests/format-recall.test.ts +30 -0
- package/vendor/pi-vcc/tests/format.test.ts +62 -0
- package/vendor/pi-vcc/tests/lineage.test.ts +33 -0
- package/vendor/pi-vcc/tests/load-messages.test.ts +51 -0
- package/vendor/pi-vcc/tests/normalize.test.ts +97 -0
- package/vendor/pi-vcc/tests/real-sessions.test.ts +38 -0
- package/vendor/pi-vcc/tests/recall-expand.test.ts +15 -0
- package/vendor/pi-vcc/tests/recall-scope.test.ts +32 -0
- package/vendor/pi-vcc/tests/recall-tool-scope.test.ts +67 -0
- package/vendor/pi-vcc/tests/render-entries.test.ts +62 -0
- package/vendor/pi-vcc/tests/report.test.ts +44 -0
- package/vendor/pi-vcc/tests/sanitize.test.ts +24 -0
- package/vendor/pi-vcc/tests/search-entries.test.ts +144 -0
- package/vendor/pi-vcc/tests/support/load-session.ts +23 -0
- package/vendor/pi-vcc/tests/support/real-sessions.ts +51 -0
- package/.agents/skills/firecrawl/SKILL.md +0 -150
- package/.agents/skills/firecrawl/rules/install.md +0 -82
- package/.agents/skills/firecrawl/rules/security.md +0 -26
- package/.agents/skills/firecrawl-agent/SKILL.md +0 -57
- package/.agents/skills/firecrawl-build-interact/SKILL.md +0 -67
- package/.agents/skills/firecrawl-build-onboarding/SKILL.md +0 -102
- package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +0 -39
- package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +0 -20
- package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +0 -17
- package/.agents/skills/firecrawl-build-scrape/SKILL.md +0 -68
- package/.agents/skills/firecrawl-build-search/SKILL.md +0 -68
- package/.agents/skills/firecrawl-crawl/SKILL.md +0 -58
- package/.agents/skills/firecrawl-download/SKILL.md +0 -69
- package/.agents/skills/firecrawl-interact/SKILL.md +0 -83
- package/.agents/skills/firecrawl-map/SKILL.md +0 -50
- package/.agents/skills/firecrawl-parse/SKILL.md +0 -61
- package/.agents/skills/firecrawl-scrape/SKILL.md +0 -68
- package/.agents/skills/firecrawl-search/SKILL.md +0 -59
- package/.pi/pi-vcc-config.json +0 -4
- package/firecrawl/.env.template +0 -62
- package/firecrawl/README.md +0 -49
- package/firecrawl/docker-compose.yaml +0 -201
- package/firecrawl/searxng/searxng.env +0 -3
- package/firecrawl/searxng/settings.yml +0 -85
|
@@ -3,11 +3,5 @@
|
|
|
3
3
|
"enabled": true,
|
|
4
4
|
"maxRetries": 3
|
|
5
5
|
},
|
|
6
|
-
"packages": [
|
|
7
|
-
"npm:ultimate-pi",
|
|
8
|
-
"npm:@posthog/pi",
|
|
9
|
-
"npm:context-mode",
|
|
10
|
-
"npm:@tintinweb/pi-subagents",
|
|
11
|
-
"npm:@sting8k/pi-vcc"
|
|
12
|
-
]
|
|
6
|
+
"packages": ["npm:ultimate-pi", "npm:@posthog/pi", "npm:context-mode"]
|
|
13
7
|
}
|
package/.sentrux/rules.toml
CHANGED
|
@@ -35,7 +35,7 @@ order = 2
|
|
|
35
35
|
|
|
36
36
|
[[layers]]
|
|
37
37
|
name = "agents"
|
|
38
|
-
paths = [".pi/agents/*", ".pi/prompts/*", ".agents/skills/*"]
|
|
38
|
+
paths = [".pi/agents/*", ".pi/harness/agents.manifest.json", ".pi/prompts/*", ".agents/skills/*"]
|
|
39
39
|
order = 3
|
|
40
40
|
# Agent definitions, prompts, and skills
|
|
41
41
|
|
package/AGENTS.md
CHANGED
|
@@ -30,7 +30,7 @@ Created: 2026-05-14
|
|
|
30
30
|
- Harness context: **context-mode only** — never lean-ctx on harness paths (see harness-context skill)
|
|
31
31
|
- `graphify update .` after significant code changes
|
|
32
32
|
- ast-grep (`sg`) is the default code search tool — use `sg -p 'pattern'` for structural search, never grep for code
|
|
33
|
-
-
|
|
33
|
+
- Web fetch/search via `python3 "$UP_PKG/.pi/scripts/harness-web.py"` (Scrapling; see scrapling-web skill)
|
|
34
34
|
|
|
35
35
|
## graphify
|
|
36
36
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [v0.4.1] — 2026-05-17
|
|
8
|
+
|
|
9
|
+
### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **In-house VCC compaction:** vendored [pi-vcc](https://github.com/sting8k/pi-vcc) (inspired by [lllyasviel/VCC](https://github.com/lllyasviel/VCC)); removed `@sting8k/pi-vcc` npm dependency. Configuration is **env-only** (`HARNESS_VCC_COMPACTION`, `HARNESS_VCC_DEBUG`) — no `PI_VCC_CONFIG_PATH` or JSON config files. VCC overrides `/compact` and auto-compaction by default; set `HARNESS_VCC_COMPACTION=false` for Pi LLM compaction. Refresh upstream: `npm run vendor:sync-vcc`.
|
|
12
|
+
- **Harness subagents:** vendored harness-subagents extension with Sentrux bootstrap agent and related harness wiring.
|
|
13
|
+
- **Harness web:** replace Firecrawl with Scrapling-based `harness-web` CLI for search and fetch.
|
|
14
|
+
|
|
15
|
+
### 🔧 Chores
|
|
16
|
+
|
|
17
|
+
- Format `.pi/settings.json` / `.pi/settings.example.json` and refresh `graphify-out` after VCC merge.
|
|
18
|
+
|
|
5
19
|
## [v0.3.1] — 2026-05-15
|
|
6
20
|
|
|
7
21
|
### 🐛 Fixes
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -6,3 +6,11 @@
|
|
|
6
6
|
- **License:** MIT ([vendor/pi-model-router/LICENSE](vendor/pi-model-router/LICENSE))
|
|
7
7
|
- **Pinned revision:** See [vendor/pi-model-router/UPSTREAM_PIN.md](vendor/pi-model-router/UPSTREAM_PIN.md)
|
|
8
8
|
- ultimate-pi loads it from [`vendor/pi-model-router`](vendor/pi-model-router); import specifiers were adapted for `@mariozechner/pi-coding-agent` and related Pi packages.
|
|
9
|
+
|
|
10
|
+
## pi-vcc (vendored)
|
|
11
|
+
|
|
12
|
+
- **Project:** https://github.com/sting8k/pi-vcc
|
|
13
|
+
- **Conceptual basis:** https://github.com/lllyasviel/VCC (View-oriented Conversation Compiler)
|
|
14
|
+
- **License:** MIT (see upstream repository)
|
|
15
|
+
- **Pinned revision:** See [vendor/pi-vcc/UPSTREAM_PIN.md](vendor/pi-vcc/UPSTREAM_PIN.md)
|
|
16
|
+
- ultimate-pi loads it from [`vendor/pi-vcc`](vendor/pi-vcc) via [`.pi/extensions/ultimate-pi-vcc.ts`](.pi/extensions/ultimate-pi-vcc.ts). Harness configuration is env-only: `HARNESS_VCC_COMPACTION`, `HARNESS_VCC_DEBUG` ([`.pi/extensions/lib/harness-vcc-settings.ts`](.pi/extensions/lib/harness-vcc-settings.ts)). Maintainer refresh: `npm run vendor:sync-vcc`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultimate-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Ultimate AI coding harness for pi.dev — extensible skills, Obsidian wiki knowledge layer, compressed context, deterministic output",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"knowledge-base",
|
|
13
13
|
"context-compression",
|
|
14
14
|
"agent-skills",
|
|
15
|
-
"
|
|
15
|
+
"scrapling",
|
|
16
|
+
"harness-web",
|
|
16
17
|
"context-mode",
|
|
17
18
|
"vcc"
|
|
18
19
|
],
|
|
@@ -44,12 +45,14 @@
|
|
|
44
45
|
".pi/scripts",
|
|
45
46
|
".pi/lib",
|
|
46
47
|
".pi/sounds",
|
|
48
|
+
".pi/harness/env.harness.template",
|
|
47
49
|
".pi/harness/specs",
|
|
48
50
|
".pi/harness/docs",
|
|
49
51
|
".pi/harness/sentrux",
|
|
50
52
|
".pi/harness/evals",
|
|
51
53
|
".pi/harness/evolution",
|
|
52
54
|
".pi/harness/corpus",
|
|
55
|
+
".pi/harness/agents.manifest.json",
|
|
53
56
|
".pi/harness/README.md",
|
|
54
57
|
".pi/npm/package.json",
|
|
55
58
|
".pi/npm/.gitignore",
|
|
@@ -57,32 +60,33 @@
|
|
|
57
60
|
".pi/settings.example.json",
|
|
58
61
|
".pi/auto-commit.json",
|
|
59
62
|
".pi/mcp.json",
|
|
60
|
-
".pi/pi-vcc-config.json",
|
|
61
63
|
".pi/SYSTEM.md",
|
|
62
64
|
".pi/PACKAGING.md",
|
|
63
|
-
"firecrawl/docker-compose.yaml",
|
|
64
|
-
"firecrawl/.env.template",
|
|
65
|
-
"firecrawl/README.md",
|
|
66
|
-
"firecrawl/searxng",
|
|
67
65
|
"AGENTS.md",
|
|
68
66
|
"biome.json",
|
|
69
67
|
"CHANGELOG.md",
|
|
70
68
|
"README.md",
|
|
71
69
|
"THIRD_PARTY_NOTICES.md",
|
|
72
|
-
"vendor/pi-model-router"
|
|
70
|
+
"vendor/pi-model-router",
|
|
71
|
+
"vendor/pi-vcc"
|
|
73
72
|
],
|
|
74
73
|
"peerDependencies": {
|
|
75
74
|
"@mariozechner/pi-coding-agent": "*"
|
|
76
75
|
},
|
|
77
76
|
"scripts": {
|
|
78
|
-
"check:ts": "tsc --noEmit --target ES2023 --lib ES2023 --moduleResolution nodenext --module nodenext --skipLibCheck .pi/extensions/dotenv-loader.ts .pi/extensions/lib/posthog-node.d.ts .pi/extensions/lib/harness-posthog.ts .pi/extensions/lib/harness-paths.ts .pi/extensions/pi-model-router-harness.ts .pi/extensions/provider-payload-sanitize.ts .pi/extensions/harness-telemetry.ts .pi/extensions/trace-recorder.ts .pi/extensions/observation-bus.ts .pi/extensions/drift-monitor.ts .pi/extensions/sentrux-rules-sync.ts .pi/extensions/custom-header.ts",
|
|
77
|
+
"check:ts": "tsc --noEmit --target ES2023 --lib ES2023 --moduleResolution nodenext --module nodenext --skipLibCheck .pi/extensions/lib/harness-vcc-settings.ts .pi/extensions/dotenv-loader.ts .pi/extensions/lib/posthog-node.d.ts .pi/extensions/lib/harness-posthog.ts .pi/extensions/lib/harness-paths.ts .pi/extensions/pi-model-router-harness.ts .pi/extensions/provider-payload-sanitize.ts .pi/extensions/harness-telemetry.ts .pi/extensions/harness-ask-user.ts .pi/extensions/lib/ask-user/schema.ts .pi/extensions/lib/ask-user/types.ts .pi/extensions/lib/ask-user/validate.ts .pi/extensions/lib/ask-user/dialog.ts .pi/extensions/lib/ask-user/fallback.ts .pi/extensions/lib/ask-user/render.ts .pi/extensions/trace-recorder.ts .pi/extensions/observation-bus.ts .pi/extensions/drift-monitor.ts .pi/extensions/sentrux-rules-sync.ts .pi/extensions/custom-header.ts .pi/extensions/lib/harness-subagents/agent-loader.ts .pi/extensions/lib/harness-subagents/agent-parser.ts .pi/extensions/lib/harness-subagents/agent-manifest.ts .pi/extensions/lib/harness-subagents/blackboard.ts .pi/extensions/lib/harness-subagents/blackboard-tool.ts .pi/extensions/lib/harness-subagents/spawn-policy.ts .pi/extensions/lib/harness-subagents/types-blackboard.ts",
|
|
79
78
|
"vendor:sync-router": "bash .pi/scripts/vendor-sync-pi-model-router.sh",
|
|
79
|
+
"vendor:sync-vcc": "bash .pi/scripts/vendor-sync-pi-vcc.sh",
|
|
80
|
+
"release": "bash .pi/scripts/release.sh",
|
|
80
81
|
"lint": "biome check",
|
|
81
82
|
"lint:fix": "biome check --fix",
|
|
82
83
|
"format": "biome format --write",
|
|
83
84
|
"format:check": "biome format",
|
|
84
85
|
"prepare": "lefthook install",
|
|
85
|
-
"test": "node --test test/harness-verify.test.mjs",
|
|
86
|
+
"test": "node --test test/harness-verify.test.mjs test/harness-ask-user.test.mjs test/harness-subagents-loader.test.mjs test/sentrux-rules-sync.test.mjs && npx -y tsx --test test/harness-vcc-settings.test.ts",
|
|
87
|
+
"test:vcc": "npx -y tsx --test vendor/pi-vcc/tests/*.test.ts",
|
|
88
|
+
"harness:sentrux-bootstrap": "node .pi/scripts/harness-sentrux-bootstrap.mjs",
|
|
89
|
+
"harness:sentrux-sync": "node .pi/scripts/sentrux-rules-sync.mjs --force",
|
|
86
90
|
"test:integration": "npx -y tsx --test test/cursor-sdk-provider.integration.test.ts"
|
|
87
91
|
},
|
|
88
92
|
"devDependencies": {
|
|
@@ -97,10 +101,10 @@
|
|
|
97
101
|
},
|
|
98
102
|
"dependencies": {
|
|
99
103
|
"@posthog/pi": "latest",
|
|
100
|
-
"@sting8k/pi-vcc": "^0.3.12",
|
|
101
|
-
"@tintinweb/pi-subagents": "latest",
|
|
102
104
|
"asciify-image": "^0.1.10",
|
|
105
|
+
"croner": "^9.0.0",
|
|
103
106
|
"jimp": "^1.6.1",
|
|
107
|
+
"nanoid": "^5.1.5",
|
|
104
108
|
"posthog-node": "^5.30.6"
|
|
105
109
|
}
|
|
106
110
|
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# pi-vcc
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@sting8k/pi-vcc)
|
|
4
|
+
|
|
5
|
+
Algorithmic conversation compactor for [Pi](https://github.com/badlogic/pi-mono). No LLM calls — produces a brief transcript via extraction and formatting.
|
|
6
|
+
|
|
7
|
+
Inspired by [VCC](https://github.com/lllyasviel/VCC) **(View-oriented Conversation Compiler)**.
|
|
8
|
+
|
|
9
|
+
## Demo
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Why pi-vcc
|
|
14
|
+
|
|
15
|
+
| | Pi default | pi-vcc |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| **Method** | LLM-generated summary | Algorithmic extraction, no LLM |
|
|
18
|
+
| **Determinism** | Non-deterministic, can hallucinate | Same input = same output, always |
|
|
19
|
+
| **Token reduction** | Varies | 35-99% on real sessions (higher on longer sessions) |
|
|
20
|
+
| **Compaction latency** | Waits for LLM call | 30-470ms, no API calls |
|
|
21
|
+
| **History after compaction** | Gone — agent only sees summary | Active lineage searchable via `vcc_recall` (`scope:"all"` available) |
|
|
22
|
+
| **Repeated compactions** | Each rewrite risks losing more | Sections merge and accumulate |
|
|
23
|
+
| **Cost** | Burns tokens on summarization call | Zero — no API calls |
|
|
24
|
+
| **Structure** | Free-form prose | Brief transcript + 4 semantic sections |
|
|
25
|
+
|
|
26
|
+
### Real session metrics
|
|
27
|
+
|
|
28
|
+
Measured on real session JSONLs under `~/.pi/agent/sessions` (chars = rendered message text).
|
|
29
|
+
|
|
30
|
+
| Session | Messages | Before | After | Reduction | Time |
|
|
31
|
+
|---|---|---|---|---|---|
|
|
32
|
+
| Session A | 2,943 | 997,162 | 7,959 | 99.2% | 64ms |
|
|
33
|
+
| Session B | 1,703 | 428,334 | 7,762 | 98.2% | 29ms |
|
|
34
|
+
| Session C | 1,657 | 424,183 | 9,577 | 97.7% | 54ms |
|
|
35
|
+
| Session D | 1,004 | 2,258,477 | 4,439 | 99.8% | 30ms |
|
|
36
|
+
| Session E | 486 | 295,006 | 11,163 | 96.2% | 30ms |
|
|
37
|
+
| Session F | 46 | 5,234 | 3,364 | 35.7% | 5ms |
|
|
38
|
+
| Session G | 27 | 8,595 | 2,489 | 71.0% | 2ms |
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- **No LLM** — purely algorithmic, zero extra API cost
|
|
43
|
+
- **Brief transcript** — chronological conversation flow, each tool call collapsed to a one-liner with `(#N)` refs, text truncated to keep it compact
|
|
44
|
+
- **5 semantic sections** — session goal, files & changes, commits, outstanding context, user preferences
|
|
45
|
+
- **Bounded merge** — rolling sections re-capped after merge instead of growing unbounded
|
|
46
|
+
- **Lossless recall** — `vcc_recall` reads raw session JSONL, so active-lineage history stays searchable across compactions
|
|
47
|
+
- **Scoped recall** — default search is active lineage; use `scope:"all"` / `scope:all` to intentionally search across all lineages
|
|
48
|
+
- **Regex search** — `vcc_recall` supports regex patterns (`hook|inject`, `fail.*build`) and OR-ranked multi-word queries
|
|
49
|
+
- **Result ranking** — search results ranked by term relevance, rare terms weighted higher than common ones
|
|
50
|
+
- **`/pi-vcc-recall`** — slash command to search history directly, results shown as collapsible message and auto-fed to agent as context
|
|
51
|
+
- **Fallback cut** — still works when Pi core returns nothing to summarize
|
|
52
|
+
- **`/pi-vcc`** — manual compaction on demand
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pi install npm:@sting8k/pi-vcc
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or from GitHub:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pi install https://github.com/sting8k/pi-vcc
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Or try without installing:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pi -e https://github.com/sting8k/pi-vcc
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
Once installed, pi-vcc registers a `session_before_compact` hook.
|
|
75
|
+
|
|
76
|
+
- Run `/pi-vcc` to trigger pi-vcc compaction manually.
|
|
77
|
+
- By default, `/compact` and auto-threshold compactions still go through pi core (LLM-based). Set `overrideDefaultCompaction: true` in the config to let pi-vcc handle all compaction paths.
|
|
78
|
+
- To search older active-lineage history after compaction, use `vcc_recall`.
|
|
79
|
+
- To intentionally search across all lineages, pass `scope:"all"` to `vcc_recall` or run `/pi-vcc-recall <query> scope:all`.
|
|
80
|
+
- To search and feed results to agent yourself, run `/pi-vcc-recall <query> [page:N]`.
|
|
81
|
+
- Tip: type `/recall` and Pi will autocomplete to `/pi-vcc-recall`.
|
|
82
|
+
|
|
83
|
+
### How compaction works
|
|
84
|
+
|
|
85
|
+
Pi splits the conversation at the **last user message**. Everything after — the **kept tail** — stays intact and untouched. pi-vcc only summarizes the older portion before that cut point.
|
|
86
|
+
|
|
87
|
+
### Compacted message structure
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
[Session Goal]
|
|
91
|
+
- Fix the authentication bug in login flow
|
|
92
|
+
- [Scope change]
|
|
93
|
+
- Also update the session token refresh logic
|
|
94
|
+
|
|
95
|
+
[Files And Changes]
|
|
96
|
+
- Modified: src/auth/session.ts
|
|
97
|
+
- Created: tests/auth-refresh.test.ts
|
|
98
|
+
|
|
99
|
+
[Commits]
|
|
100
|
+
- a1b2c3d: fix(auth): refresh token after password reset
|
|
101
|
+
|
|
102
|
+
[Outstanding Context]
|
|
103
|
+
- lint check still failing on line 42
|
|
104
|
+
|
|
105
|
+
[User Preferences]
|
|
106
|
+
- Prefer Vietnamese responses
|
|
107
|
+
- Always run tests before committing
|
|
108
|
+
|
|
109
|
+
[user]
|
|
110
|
+
Fix the auth bug, users can't log in after password reset
|
|
111
|
+
|
|
112
|
+
[assistant]
|
|
113
|
+
Root cause is a missing token refresh after password reset...
|
|
114
|
+
* bash "bun test tests/auth.test.ts" (#12)
|
|
115
|
+
* edit "src/auth/session.ts" (#14)
|
|
116
|
+
* bash "bun test tests/auth.test.ts" (#16)
|
|
117
|
+
...(28 earlier lines omitted)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Sections appear only when relevant — a session with no git commits won't have `[Commits]`.
|
|
121
|
+
|
|
122
|
+
**Sections:**
|
|
123
|
+
|
|
124
|
+
| Section | Description |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `[Session Goal]` | Initial goal + scope changes (regex-based extraction) |
|
|
127
|
+
| `[Files And Changes]` | Modified/created files from tool calls (capped, paths trimmed to common root) |
|
|
128
|
+
| `[Commits]` | Git commits made during the session (last 8, hash + first line) |
|
|
129
|
+
| `[Outstanding Context]` | Unresolved items — errors, pending questions |
|
|
130
|
+
| `[User Preferences]` | Regex-extracted from user messages (`always`, `never`, `prefer`...) |
|
|
131
|
+
| Brief transcript | Chronological conversation flow — rolling window of ~120 recent lines, tool calls collapsed to one-liners with `(#N)` refs |
|
|
132
|
+
|
|
133
|
+
**Merge policy:**
|
|
134
|
+
- `Session Goal`, `User Preferences`: concise sticky sections
|
|
135
|
+
- `Outstanding Context`: fresh-only (replaced each compaction)
|
|
136
|
+
- `Files And Changes`, `Commits`: unique union across compactions
|
|
137
|
+
- Brief transcript: rolling window, older lines drop off
|
|
138
|
+
|
|
139
|
+
## Recall (Lossless History)
|
|
140
|
+
|
|
141
|
+
Pi's default compaction discards old messages permanently. After compaction, the agent only sees the summary.
|
|
142
|
+
|
|
143
|
+
`vcc_recall` bypasses this by reading the raw session JSONL file directly. By default it searches only the active conversation lineage, regardless of how many compactions have happened. Use `scope:"all"` only when you intentionally want to include off-lineage branches.
|
|
144
|
+
|
|
145
|
+
### Search
|
|
146
|
+
|
|
147
|
+
Queries support **regex** and **multi-word OR logic** ranked by relevance:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
vcc_recall({ query: "auth token" }) // active-lineage OR search, ranked
|
|
151
|
+
vcc_recall({ query: "auth token", page: 2 }) // paginated (5 results/page)
|
|
152
|
+
vcc_recall({ query: "hook|inject" }) // regex pattern
|
|
153
|
+
vcc_recall({ query: "fail.*build" }) // regex pattern
|
|
154
|
+
vcc_recall({ query: "auth token", scope: "all" }) // search all lineages
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Manual slash command:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
/pi-vcc-recall auth token scope:all
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Browse
|
|
164
|
+
|
|
165
|
+
Without a query, returns the last 25 entries as brief summaries:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
vcc_recall()
|
|
169
|
+
vcc_recall({ scope: "all" }) // browse recent entries across all lineages
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Expand
|
|
173
|
+
|
|
174
|
+
Returns full untruncated content for specific indices found via search:
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
vcc_recall({ expand: [41, 42] }) // active-lineage expand
|
|
178
|
+
vcc_recall({ expand: [41, 42], scope: "all" }) // expand across all lineages
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Typical workflow: **search → find relevant entry indices → expand those indices for full content**.
|
|
182
|
+
|
|
183
|
+
> Some tool results are truncated by Pi core at save time. `expand` returns everything in the JSONL but can't recover what Pi already cut.
|
|
184
|
+
|
|
185
|
+
## Pipeline
|
|
186
|
+
|
|
187
|
+
1. **Normalize** — raw Pi messages → uniform blocks (user, assistant, tool_call, tool_result, thinking)
|
|
188
|
+
2. **Filter noise** — strip system messages, empty blocks
|
|
189
|
+
3. **Build sections** — extract goal, file paths, blockers, preferences
|
|
190
|
+
4. **Brief transcript** — chronological conversation flow, tool calls collapsed to one-liners, text truncated
|
|
191
|
+
5. **Format** — render into bracketed sections + transcript
|
|
192
|
+
6. **Merge** — if previous summary exists: sticky sections merge, volatile sections replace, transcript rolls
|
|
193
|
+
|
|
194
|
+
## Config
|
|
195
|
+
|
|
196
|
+
Config lives at `~/.pi/agent/pi-vcc-config.json` (auto-scaffolded on first load with safe defaults):
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"overrideDefaultCompaction": false,
|
|
201
|
+
"debug": false
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- **`overrideDefaultCompaction`** *(default `false`)*: when `false`, pi-vcc only runs for `/pi-vcc`; `/compact` and auto-threshold compactions fall through to pi core. Set `true` to make pi-vcc handle all compaction paths.
|
|
206
|
+
- **`debug`** *(default `false`)*: when `true`, each compaction writes detailed info to `/tmp/pi-vcc-debug.json` — message counts, cut boundary, summary preview, sections.
|
|
207
|
+
|
|
208
|
+
## Related Work
|
|
209
|
+
|
|
210
|
+
- [VCC](https://github.com/lllyasviel/VCC) — the original transcript-preserving conversation compiler
|
|
211
|
+
- [Pi](https://github.com/badlogic/pi-mono) — the AI coding agent this extension is built for
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Vendored `pi-vcc`
|
|
2
|
+
|
|
3
|
+
- **Repository:** https://github.com/sting8k/pi-vcc
|
|
4
|
+
- **Conceptual basis:** [lllyasviel/VCC](https://github.com/lllyasviel/VCC) (View-oriented Conversation Compiler)
|
|
5
|
+
- **License:** MIT (see upstream repository)
|
|
6
|
+
- **Pinned upstream commit:** `3e0b49e4ef605370e3dd92889e6b70502262cc28`
|
|
7
|
+
- **Local changes:**
|
|
8
|
+
- `src/core/settings.ts` re-exports env-only [`.pi/extensions/lib/harness-vcc-settings.ts`](../../.pi/extensions/lib/harness-vcc-settings.ts) (`HARNESS_VCC_COMPACTION`, `HARNESS_VCC_DEBUG`)
|
|
9
|
+
- No `scaffoldSettings` / no `PI_VCC_CONFIG_PATH`
|
|
10
|
+
- Compaction `details.compactor` is `ultimate-pi-vcc`
|
|
11
|
+
|
|
12
|
+
**Refresh upstream:** run `npm run vendor:sync-vcc` from ultimate-pi root.
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import { registerBeforeCompactHook } from "./src/hooks/before-compact";
|
|
3
|
+
import { registerPiVccCommand } from "./src/commands/pi-vcc";
|
|
4
|
+
import { registerVccRecallCommand } from "./src/commands/vcc-recall";
|
|
5
|
+
import { registerRecallTool } from "./src/tools/recall";
|
|
6
|
+
|
|
7
|
+
export default (pi: ExtensionAPI) => {
|
|
8
|
+
registerBeforeCompactHook(pi);
|
|
9
|
+
registerPiVccCommand(pi);
|
|
10
|
+
registerVccRecallCommand(pi);
|
|
11
|
+
registerRecallTool(pi);
|
|
12
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sting8k/pi-vcc",
|
|
3
|
+
"version": "0.3.13",
|
|
4
|
+
"description": "Algorithmic conversation compactor for pi - transcript-preserving structured summaries, no LLM calls",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension",
|
|
9
|
+
"vcc",
|
|
10
|
+
"compact",
|
|
11
|
+
"compaction"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/sting8k/pi-vcc.git"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
19
|
+
"@sinclair/typebox": "*"
|
|
20
|
+
},
|
|
21
|
+
"pi": {
|
|
22
|
+
"extensions": [
|
|
23
|
+
"./index.ts"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { basename, dirname } from "node:path";
|
|
2
|
+
import { compile } from "../src/core/summarize";
|
|
3
|
+
import { normalize } from "../src/core/normalize";
|
|
4
|
+
import { filterNoise } from "../src/core/filter-noise";
|
|
5
|
+
import { renderMessage } from "../src/core/render-entries";
|
|
6
|
+
import { prepareSessionSamples } from "../tests/support/real-sessions";
|
|
7
|
+
import { loadSessionMessages } from "../tests/support/load-session";
|
|
8
|
+
|
|
9
|
+
const SEP = "=".repeat(80);
|
|
10
|
+
const samples = await prepareSessionSamples(10);
|
|
11
|
+
|
|
12
|
+
for (const sample of samples) {
|
|
13
|
+
const loaded = loadSessionMessages(sample.copy);
|
|
14
|
+
const { messages } = loaded;
|
|
15
|
+
|
|
16
|
+
const rawBlocks = normalize(messages);
|
|
17
|
+
const filteredBlocks = filterNoise(rawBlocks);
|
|
18
|
+
const afterText = compile({ messages });
|
|
19
|
+
|
|
20
|
+
const rendered = messages.map((m, i) => renderMessage(m, i));
|
|
21
|
+
const beforeChars = rendered.reduce((s, e) => s + e.summary.length, 0);
|
|
22
|
+
|
|
23
|
+
const project = dirname(sample.source).split("--").filter(Boolean).pop() ?? "unknown";
|
|
24
|
+
|
|
25
|
+
const goalSection = afterText.match(/\[Session Goal\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
|
|
26
|
+
const stateSection = afterText.match(/\[Current State\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
|
|
27
|
+
const doneSection = afterText.match(/\[What Was Done\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
|
|
28
|
+
const problemsSection = afterText.match(/\[Open Problems\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
|
|
29
|
+
const nextSection = afterText.match(/\[Next Best Steps\]\n([\s\S]*?)(?=\n\n\[|$)/)?.[1] ?? "(empty)";
|
|
30
|
+
|
|
31
|
+
const doneLines = doneSection.split("\n").filter(l => l.trim());
|
|
32
|
+
const problemLines = problemsSection.split("\n").filter(l => l.trim());
|
|
33
|
+
|
|
34
|
+
// Detect issues
|
|
35
|
+
const issues: string[] = [];
|
|
36
|
+
|
|
37
|
+
// 1. Goal quality
|
|
38
|
+
const goalLines = goalSection.split("\n").map(l => l.replace(/^- /, "").trim()).filter(Boolean);
|
|
39
|
+
if (goalLines[0] && goalLines[0].length < 5) issues.push(`GOAL_TOO_SHORT: "${goalLines[0]}"`);
|
|
40
|
+
if (goalLines.length === 0) issues.push("GOAL_EMPTY");
|
|
41
|
+
|
|
42
|
+
// 2. Sensitive data in What Was Done
|
|
43
|
+
if (/sshpass|password|secret|token=|api[_-]?key/i.test(doneSection)) {
|
|
44
|
+
issues.push("SENSITIVE_DATA_IN_DONE");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Raw code/minified JS in summary
|
|
48
|
+
if (/\{[a-zA-Z$_]+:[a-zA-Z$_]+,[a-zA-Z$_]+:/.test(afterText) || /var [a-zA-Z]+=/.test(afterText)) {
|
|
49
|
+
issues.push("RAW_CODE_LEAK");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// 4. Open problems count
|
|
53
|
+
if (problemLines.length > 10) issues.push(`PROBLEMS_OVERCOUNT: ${problemLines.length}`);
|
|
54
|
+
|
|
55
|
+
// 5. Next steps empty
|
|
56
|
+
if (nextSection === "(empty)") issues.push("NEXT_STEPS_EMPTY");
|
|
57
|
+
|
|
58
|
+
// 6. What Was Done too verbose
|
|
59
|
+
if (doneLines.length > 15) issues.push(`DONE_TOO_VERBOSE: ${doneLines.length} lines`);
|
|
60
|
+
|
|
61
|
+
// 7. Summary too large (>10K chars)
|
|
62
|
+
if (afterText.length > 10000) issues.push(`SUMMARY_TOO_LARGE: ${afterText.length} chars`);
|
|
63
|
+
|
|
64
|
+
console.log(SEP);
|
|
65
|
+
console.log(`PROJECT: ${project}`);
|
|
66
|
+
console.log(`FILE: ${basename(sample.source)}`);
|
|
67
|
+
console.log(`Size: ${(sample.size / 1024).toFixed(0)}KB | Msgs: ${messages.length} | Blocks raw: ${rawBlocks.length} -> filtered: ${filteredBlocks.length}`);
|
|
68
|
+
console.log(`Before: ${beforeChars} chars | After: ${afterText.length} chars | Ratio: ${(beforeChars / afterText.length).toFixed(1)}x`);
|
|
69
|
+
console.log(`Issues: ${issues.length === 0 ? "NONE" : issues.join(", ")}`);
|
|
70
|
+
console.log("");
|
|
71
|
+
console.log("--- GOAL ---");
|
|
72
|
+
console.log(goalSection.slice(0, 300));
|
|
73
|
+
console.log("");
|
|
74
|
+
console.log("--- CURRENT STATE (first 300c) ---");
|
|
75
|
+
console.log(stateSection.slice(0, 300));
|
|
76
|
+
console.log("");
|
|
77
|
+
console.log("--- WHAT WAS DONE (first 5 lines) ---");
|
|
78
|
+
console.log(doneLines.slice(0, 5).join("\n"));
|
|
79
|
+
console.log(`... (${doneLines.length} total lines)`);
|
|
80
|
+
console.log("");
|
|
81
|
+
console.log("--- OPEN PROBLEMS (first 5 lines) ---");
|
|
82
|
+
console.log(problemLines.slice(0, 5).join("\n"));
|
|
83
|
+
console.log(`... (${problemLines.length} total lines)`);
|
|
84
|
+
console.log("");
|
|
85
|
+
console.log("--- NEXT STEPS ---");
|
|
86
|
+
console.log(nextSection.slice(0, 300));
|
|
87
|
+
console.log("");
|
|
88
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { buildCompactReport } from "../src/core/report";
|
|
4
|
+
import { prepareSessionSamples } from "../tests/support/real-sessions";
|
|
5
|
+
import { loadSessionMessages } from "../tests/support/load-session";
|
|
6
|
+
|
|
7
|
+
const samples = await prepareSessionSamples(2);
|
|
8
|
+
for (const sample of samples) {
|
|
9
|
+
const loaded = loadSessionMessages(sample.copy);
|
|
10
|
+
const start = performance.now();
|
|
11
|
+
const report = buildCompactReport({ messages: loaded.messages });
|
|
12
|
+
const elapsedMs = performance.now() - start;
|
|
13
|
+
console.log(JSON.stringify({
|
|
14
|
+
sourceFile: basename(sample.source),
|
|
15
|
+
sourceSizeBytes: sample.size,
|
|
16
|
+
copiedToTemp: true,
|
|
17
|
+
loadedMessages: loaded.messageCount,
|
|
18
|
+
skippedMessages: loaded.skippedCount,
|
|
19
|
+
compileMs: Number(elapsedMs.toFixed(2)),
|
|
20
|
+
before: report.before,
|
|
21
|
+
after: report.after,
|
|
22
|
+
compression: report.compression,
|
|
23
|
+
recall: report.recall,
|
|
24
|
+
}, null, 2));
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { compile } from "../src/core/summarize";
|
|
3
|
+
import { renderMessage } from "../src/core/render-entries";
|
|
4
|
+
import { clip } from "../src/core/content";
|
|
5
|
+
import { prepareSessionSamples } from "../tests/support/real-sessions";
|
|
6
|
+
import { loadSessionMessages } from "../tests/support/load-session";
|
|
7
|
+
|
|
8
|
+
const SEP = "=".repeat(80);
|
|
9
|
+
const samples = await prepareSessionSamples(2);
|
|
10
|
+
|
|
11
|
+
for (const sample of samples) {
|
|
12
|
+
const loaded = loadSessionMessages(sample.copy);
|
|
13
|
+
const { messages } = loaded;
|
|
14
|
+
|
|
15
|
+
const rendered = messages.map((m, i) => renderMessage(m, i));
|
|
16
|
+
const beforeLines = rendered.map(
|
|
17
|
+
(e) => `#${e.index} [${e.role}] ${clip(e.summary, 300)}`,
|
|
18
|
+
);
|
|
19
|
+
const beforeText = beforeLines.join("\n");
|
|
20
|
+
const afterText = compile({ messages });
|
|
21
|
+
|
|
22
|
+
console.log(SEP);
|
|
23
|
+
console.log(`FILE: ${basename(sample.source)}`);
|
|
24
|
+
console.log(`Messages: ${messages.length} | Before chars: ${beforeText.length} | After chars: ${afterText.length}`);
|
|
25
|
+
console.log(`Compression: ${(beforeText.length / afterText.length).toFixed(1)}x`);
|
|
26
|
+
console.log(SEP);
|
|
27
|
+
|
|
28
|
+
console.log("\n--- BEFORE (raw context, first 40 + last 20 entries) ---\n");
|
|
29
|
+
for (const line of beforeLines.slice(0, 40)) console.log(line);
|
|
30
|
+
if (beforeLines.length > 60) console.log(`\n... (${beforeLines.length - 60} entries omitted) ...\n`);
|
|
31
|
+
for (const line of beforeLines.slice(-20)) console.log(line);
|
|
32
|
+
|
|
33
|
+
console.log("\n--- AFTER (pi-vcc compiled summary) ---\n");
|
|
34
|
+
console.log(afterText);
|
|
35
|
+
console.log("\n");
|
|
36
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { compile } from "../src/core/summarize";
|
|
3
|
+
import { prepareSessionSamples } from "../tests/support/real-sessions";
|
|
4
|
+
import { loadSessionMessages } from "../tests/support/load-session";
|
|
5
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
6
|
+
|
|
7
|
+
const outDir = "/tmp/pi-vcc-compare";
|
|
8
|
+
const branch = process.argv[2] || "unknown";
|
|
9
|
+
mkdirSync(`${outDir}/${branch}`, { recursive: true });
|
|
10
|
+
|
|
11
|
+
const samples = await prepareSessionSamples(5);
|
|
12
|
+
for (const sample of samples) {
|
|
13
|
+
const name = basename(sample.source).slice(0, 30);
|
|
14
|
+
const loaded = loadSessionMessages(sample.copy);
|
|
15
|
+
const summary = compile({ messages: loaded.messages });
|
|
16
|
+
const outFile = `${outDir}/${branch}/${name}.txt`;
|
|
17
|
+
writeFileSync(outFile, summary);
|
|
18
|
+
console.log(`${name} (${loaded.messageCount} msgs) => ${summary.length} chars`);
|
|
19
|
+
}
|
|
20
|
+
console.log(`\nSaved to ${outDir}/${branch}/`);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import { getLastCompactionStats, PI_VCC_COMPACT_INSTRUCTION } from "../hooks/before-compact";
|
|
3
|
+
|
|
4
|
+
const formatTokens = (n: number): string => {
|
|
5
|
+
if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
|
|
6
|
+
return String(n);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const registerPiVccCommand = (pi: ExtensionAPI) => {
|
|
10
|
+
pi.registerCommand("pi-vcc", {
|
|
11
|
+
description: "Compact conversation with pi-vcc structured summary",
|
|
12
|
+
handler: async (_args, ctx) => {
|
|
13
|
+
ctx.compact({
|
|
14
|
+
customInstructions: PI_VCC_COMPACT_INSTRUCTION,
|
|
15
|
+
onComplete: () => {
|
|
16
|
+
const stats = getLastCompactionStats();
|
|
17
|
+
if (stats) {
|
|
18
|
+
ctx.ui.notify(
|
|
19
|
+
`pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok).`,
|
|
20
|
+
"info",
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
ctx.ui.notify("Compacted with pi-vcc", "info");
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
onError: (err) => {
|
|
27
|
+
if (err.message === "Compaction cancelled" || err.message === "Already compacted") {
|
|
28
|
+
ctx.ui.notify("Nothing to compact", "warning");
|
|
29
|
+
} else {
|
|
30
|
+
ctx.ui.notify(`Compaction failed: ${err.message}`, "error");
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
};
|