@caupulican/pi-adaptative 0.80.99 → 0.80.102
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 +203 -0
- package/dist/core/agent-session.d.ts +72 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +437 -46
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts +5 -0
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +28 -4
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/path-scope.d.ts.map +1 -1
- package/dist/core/autonomy/path-scope.js +33 -2
- package/dist/core/autonomy/path-scope.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +15 -7
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/context/brain-curator.d.ts +10 -0
- package/dist/core/context/brain-curator.d.ts.map +1 -1
- package/dist/core/context/brain-curator.js +19 -2
- package/dist/core/context/brain-curator.js.map +1 -1
- package/dist/core/context-gc.d.ts +8 -3
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +5 -0
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/delegation/worker-actions.d.ts +0 -10
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +5 -7
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-result.d.ts +6 -0
- package/dist/core/delegation/worker-result.d.ts.map +1 -1
- package/dist/core/delegation/worker-result.js +10 -4
- package/dist/core/delegation/worker-result.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +3 -0
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +6 -1
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/doctor.d.ts +66 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +144 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/learning/learning-audit.d.ts +13 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js +22 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/learning-gate.d.ts +3 -0
- package/dist/core/learning/learning-gate.d.ts.map +1 -1
- package/dist/core/learning/learning-gate.js +13 -4
- package/dist/core/learning/learning-gate.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts +34 -0
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -0
- package/dist/core/models/default-model-suggestions.js +58 -0
- package/dist/core/models/default-model-suggestions.js.map +1 -0
- package/dist/core/models/local-registration.d.ts +2 -0
- package/dist/core/models/local-registration.d.ts.map +1 -1
- package/dist/core/models/local-registration.js +2 -1
- package/dist/core/models/local-registration.js.map +1 -1
- package/dist/core/models/local-runtime.d.ts +76 -2
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +233 -21
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/profile-resource-selection.d.ts +15 -3
- package/dist/core/profile-resource-selection.d.ts.map +1 -1
- package/dist/core/profile-resource-selection.js +19 -9
- package/dist/core/profile-resource-selection.js.map +1 -1
- package/dist/core/resource-loader.d.ts +20 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +42 -16
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +30 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +65 -3
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +14 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +8 -0
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tools/fff-search-backend.d.ts +34 -1
- package/dist/core/tools/fff-search-backend.d.ts.map +1 -1
- package/dist/core/tools/fff-search-backend.js +43 -4
- package/dist/core/tools/fff-search-backend.js.map +1 -1
- package/dist/core/tools/find.d.ts +16 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +17 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +20 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +15 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +17 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts +6 -2
- package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.js +55 -45
- package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-suggestion-selector.d.ts +13 -0
- package/dist/modes/interactive/components/model-suggestion-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-suggestion-selector.js +40 -0
- package/dist/modes/interactive/components/model-suggestion-selector.js.map +1 -0
- package/dist/modes/interactive/components/profile-resource-editor.d.ts +3 -0
- package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.js +16 -2
- package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +98 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +57 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/safe-write-stream.d.ts +8 -0
- package/dist/utils/safe-write-stream.d.ts.map +1 -1
- package/dist/utils/safe-write-stream.js +32 -0
- package/dist/utils/safe-write-stream.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +92 -2
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +172 -32
- package/dist/utils/tools-manager.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -36
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,206 @@
|
|
|
1
|
+
## [0.80.102] - 2026-07-03
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- Made the FFF lazy-install test suite environment-independent. Three tests asserted that
|
|
6
|
+
`@ff-labs/fff-node` was not resolvable — which held locally (the package resolves only via the
|
|
7
|
+
managed install) but failed in CI, where the declared dependency is installed by `npm ci`,
|
|
8
|
+
blocking v0.80.101 from publishing. `loadAvailableFffNodePackage`/`ensureFffNodePackage` now take
|
|
9
|
+
an optional injectable resolver-candidate list, and those tests pass an empty list to force the
|
|
10
|
+
"not available" precondition deterministically regardless of environment. Test-only; no runtime
|
|
11
|
+
behavior change. 0.80.102 republishes the 0.80.101 changes with this fix.
|
|
12
|
+
|
|
13
|
+
## [0.80.101] - 2026-07-03
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Skills may declare a `thinking` level in their frontmatter (parsed and validated on load, invalid
|
|
18
|
+
values ignored), so a task-specific skill can carry its intended reasoning depth. The parsed value
|
|
19
|
+
is available wherever `Skill` objects flow; turn-scoped application of an active skill's thinking
|
|
20
|
+
is a follow-up (an extension can already apply it via the existing `ctx.setThinkingLevel()` hook).
|
|
21
|
+
Complements profile-level thinking, which is applied to the session across CLI startup, SDK
|
|
22
|
+
creation, `/profile` switch, and `/reload` (explicit `--thinking` still wins) — now covered by
|
|
23
|
+
tests, including its composition with per-tier router thinking (the router override wins for the
|
|
24
|
+
routed turn and restores the profile level after).
|
|
25
|
+
- Per-tier thinking level for the model router: `modelRouter` now accepts `cheapThinking`,
|
|
26
|
+
`mediumThinking`, `expensiveThinking`, `executorThinking`, and `judgeThinking`. A routed turn
|
|
27
|
+
applies the configured thinking level for its tier (clamped to the routed model), so a
|
|
28
|
+
cheap/local tier can run at `low`/`off` while the expensive tier runs at `high` — thinking level
|
|
29
|
+
is now a cost/speed lever independent of the model choice. Unset per-tier thinking reproduces
|
|
30
|
+
today's inherit-and-clamp behavior exactly; the routing judge's own bounded completion uses
|
|
31
|
+
`judgeThinking` (default `off`). Executor-direct routes are matched before the cheap tier so they
|
|
32
|
+
read `executorThinking`, not `cheapThinking`. Each tier's thinking level is settable in the Model
|
|
33
|
+
Router settings submenu (an "(inherit)" option clears it to the default behavior).
|
|
34
|
+
- `/models suggest` now opens an interactive picker over the validated local-model roster instead of
|
|
35
|
+
printing a list to retype: choosing a model installs it, probes its six fitness surfaces on the
|
|
36
|
+
actual hardware, and lands the role it was shaped for already pre-selected in the assignment step —
|
|
37
|
+
so a suggested model goes from pick to installed-and-set in one flow. The suggestion's shaped
|
|
38
|
+
`assignRole` (previously unused metadata) drives the pre-selection; non-tool-calling models carry
|
|
39
|
+
curator/judge/lane roles and never pre-select the executor role.
|
|
40
|
+
- The model router now auto-manages the local ollama server: when a turn routes to a local (ollama)
|
|
41
|
+
model, pi ensures the server is up first — reusing an already-running server and the user's own
|
|
42
|
+
`~/.ollama` models (never pi's owned storage; a reuse-mode start omits the `OLLAMA_MODELS` override
|
|
43
|
+
that `/models add` still uses) or booting one if needed — so a local-routed turn never fails just
|
|
44
|
+
because the server wasn't started yet. A per-session "confirmed up" cache skips the health check on
|
|
45
|
+
later turns (re-checked only after a connection error from the same model). If the local model
|
|
46
|
+
can't be made ready (binary missing, or the server won't boot) the turn does not dead-end: a
|
|
47
|
+
visible warning states why (install steps inline when the binary is missing) and which tier is now
|
|
48
|
+
handling the turn, then it escalates to the next configured tier. The runtime is owned by
|
|
49
|
+
`AgentSession`, so headless/SDK turns get the same behavior and `/models` shares the one instance.
|
|
50
|
+
- When a routed local model is missing only because the ollama binary itself isn't installed (not
|
|
51
|
+
because its server is down), an interactive session now asks first: "Install Ollama?", noting it's
|
|
52
|
+
a large one-time download, before doing anything. A "yes" downloads the pinned ollama release for
|
|
53
|
+
the current platform straight into pi's own `runtimes/ollama` directory (never `curl | sh`, never
|
|
54
|
+
outside pi's own directory) and extracts it — `.tar.zst` archives decompress via Node's own
|
|
55
|
+
built-in zstd support when available, falling back to a system `zstd` binary, with an honest error
|
|
56
|
+
if neither exists — then the turn proceeds on the original local model with no fallback needed. A
|
|
57
|
+
"no", a timeout, an install that itself fails, or a headless/SDK session with no interactive prompt
|
|
58
|
+
to ask through all fall straight through to the existing graceful tier-escalation warning above,
|
|
59
|
+
worded to say so honestly (an install attempt that failed is reported as a failed install attempt,
|
|
60
|
+
never re-labeled as if nothing was tried). The confirm dialog pauses the routing working-indicator
|
|
61
|
+
while it's on screen and hands it back right after, so the spinner and the dialog never compete for
|
|
62
|
+
the terminal at the same time.
|
|
63
|
+
- New `pi-adaptative doctor` command plus an update/startup preflight that verify required tooling and
|
|
64
|
+
provision what pi owns. It checks FFF native search (managed — actually installs it if missing, via
|
|
65
|
+
the same path as lazy first-use), ripgrep, ollama (binary + server status), and python, reporting
|
|
66
|
+
each as present/missing with version/detail and, for tools pi doesn't own, guide-mode install steps
|
|
67
|
+
(printed, never executed — no `curl | sh`, no `sudo`). The preflight runs automatically after a
|
|
68
|
+
successful `pi-adaptative update` (best-effort, never fails the update), so an update actually
|
|
69
|
+
provisions the managed tooling instead of leaving it to lazy first-use — closing the "ran update on
|
|
70
|
+
another machine and FFF never got installed" gap. The interactive `doctor` shows install progress;
|
|
71
|
+
the background preflight stays quiet.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- FFF native search now provisions itself even for ordinary searches. `find`/`grep` decide
|
|
76
|
+
FFF-vs-fallback using their default result limit (1000/100), which exceeds the router's top-N
|
|
77
|
+
threshold, so the decision is "fallback" and the tool returned *before* ever calling `getFinder()`
|
|
78
|
+
— the call that triggers the lazy managed install of `@ff-labs/fff-node`. A machine that only ran
|
|
79
|
+
default-limit searches therefore never installed FFF at all (rg/fd silently handled everything, so
|
|
80
|
+
its speed was never available). Provisioning is now decoupled from the per-call routing outcome:
|
|
81
|
+
`find`/`grep` kick off the finder unconditionally via a new `safeGetFinder` that can never reject
|
|
82
|
+
(even if a custom backend's `getFinder` throws synchronously), reusing the same in-flight promise
|
|
83
|
+
when the call does route to FFF. A genuine install failure is now retryable instead of permanently
|
|
84
|
+
gating FFF out — the finder is always evicted so the next search re-enters — while a 30s cooldown
|
|
85
|
+
throttles the npm spawn itself, so repeated searches during an outage don't respawn npm each time.
|
|
86
|
+
An explicit `--offline`/`PI_OFFLINE` directive and unsupported platforms remain a stable no-retry
|
|
87
|
+
fallback. The last install outcome is recorded (`getLastFffInstallOutcome`) for a future
|
|
88
|
+
environment `doctor` check.
|
|
89
|
+
- The user's prompt now appears on screen immediately when submitted, instead of appearing to hang
|
|
90
|
+
until the model router's routing judge finishes. The judge is a bounded LLM completion (seconds),
|
|
91
|
+
and the turn previously built and emitted the user message only *after* awaiting it, so the prompt
|
|
92
|
+
looked frozen right after Enter. `_promptUnserialized` now builds the user message and paints it (a
|
|
93
|
+
synthetic `message_start`) before the judge await, then reuses that same object for the turn; the
|
|
94
|
+
authoritative `message_start` emitted later is suppressed exactly once (reference-keyed via a Set),
|
|
95
|
+
so the message is still shown and persisted a single time, and extensions still observe it at the
|
|
96
|
+
real turn start (their visible behavior is unchanged).
|
|
97
|
+
- While the model router's routing/prep phase runs — the gap after the prompt paints and before the
|
|
98
|
+
turn starts streaming, during which the routing judge makes a bounded LLM call — the interactive UI
|
|
99
|
+
now shows the existing "working" indicator as general processing feedback, so that gap no longer
|
|
100
|
+
looks frozen. It shows independently of the thinking level (this is routing feedback, not
|
|
101
|
+
model-thinking) and respects the user's working-indicator toggle. New UI-only `routing_start` /
|
|
102
|
+
`routing_end` session events bracket the phase and are emitted exactly once each — `routing_end`
|
|
103
|
+
fires on both the success and failure paths, so the indicator never spins on after a turn that
|
|
104
|
+
fails before it starts — and it hands off seamlessly into the normal streaming indicator.
|
|
105
|
+
- Hardened the hardening sweep after a max-effort review of the working diff found nine regressions
|
|
106
|
+
and latent holes the first pass introduced or left open:
|
|
107
|
+
- `endWriteStream` (newly awaited by the bash executor) hung forever when the stream had already
|
|
108
|
+
errored or closed before the call — an errored stream never emits `finish`, so the `once`
|
|
109
|
+
listeners attached after the events fired and never resolved, hanging the bash tool on any spill
|
|
110
|
+
write error. It now resolves immediately for an already-finished/destroyed/closed/errored stream.
|
|
111
|
+
- The git-filter spill branch created its temp-file stream with no error handler, so a failed spill
|
|
112
|
+
write still advertised a "Full output:" path pointing at a partial or missing file. It now drops
|
|
113
|
+
the path on write error, matching the main capture path.
|
|
114
|
+
- The execution-time envelope path check resolved a target through `existsSync`, which reports
|
|
115
|
+
false for a DANGLING symlink — so a dangling symlink placed inside an allowed root resolved
|
|
116
|
+
lexically and escaped the envelope (the subsequent write follows the link). `safeRealpathSync`
|
|
117
|
+
now dereferences a dangling leaf via `lstat`/`readlink` with a hop cap, closing the escape.
|
|
118
|
+
- `applyWorkerActions` routed writes through an injectable fs seam while the scope check used the
|
|
119
|
+
real filesystem, so the two could disagree. The test-only seam (its sole injector) is removed;
|
|
120
|
+
scope check and write now share one filesystem of record.
|
|
121
|
+
- The context-GC auto-digest was fenced at RENDER time, regenerating a random boundary nonce on
|
|
122
|
+
every provider request (the GC transform re-runs per request) — a byte-unstable prompt prefix
|
|
123
|
+
that broke prefix caching, and double-wrapped/mangled an already-fenced digest. Fencing now
|
|
124
|
+
happens once at digest store time; GC renders it verbatim.
|
|
125
|
+
- A reflection write the gate marked "apply" recorded an `action:"apply"` audit with a rollback
|
|
126
|
+
plan even when the memory tool silently refused it (budget/drift/threat return `success:false`
|
|
127
|
+
without throwing) — a phantom rollback target that then failed not-found. A refused apply now
|
|
128
|
+
records an `apply_failed` audit with no rollback plan and is not rollback-eligible.
|
|
129
|
+
- The `/context` "withheld by the active resource profile" line fired even with NO active profile,
|
|
130
|
+
blaming a nonexistent profile for a plain user disable (and double-reporting alongside the
|
|
131
|
+
disable-wins warning). The count is now profile-only and empty when no profile is active.
|
|
132
|
+
- A durable `memory_replace`/`memory_remove` could never auto-apply even under a fully permissive
|
|
133
|
+
policy, because the contradiction branch short-circuited before every eligibility check — an
|
|
134
|
+
append-only incentive that degraded memory hygiene. A new `learningPolicy.autoApplySupersessions`
|
|
135
|
+
(default false, TUI-toggleable) lets a supersession fall through to the normal eligibility bars.
|
|
136
|
+
- Router-swapped turns restored the pre-turn tools/system-prompt unconditionally in `finally`,
|
|
137
|
+
silently clobbering a mid-turn extension change (e.g. `setActiveToolsByName`) that legitimately
|
|
138
|
+
replaced them. Restore now happens only when the live values are still exactly what the swap
|
|
139
|
+
assigned.
|
|
140
|
+
- The editor grant-widening guard was applied only to allow-framing: the block-framing all-enabled
|
|
141
|
+
branch still widened a closed grant to `{allow:["*"]}` for a kind the profile omitted, and the
|
|
142
|
+
editor let the literal `"*"` wildcard marker enter the working set as a fake resource id (so
|
|
143
|
+
unchecking one item under a `{allow:["*"]}` grant persisted `{allow:[…,"*"]}`, and the disabled
|
|
144
|
+
item kept loading). Both paths now gate on the same original-wildcard/grant-all check, and the
|
|
145
|
+
marker never enters the item set.
|
|
146
|
+
- Fixed `executeBash` returning a full-output temp-file path before the file's write was flushed:
|
|
147
|
+
the artifact write went through an async stream that was `.end()`-ed but never awaited, so a caller
|
|
148
|
+
reading the path immediately could see partial or empty content (a load-dependent flake). The stream
|
|
149
|
+
flush is now awaited across the normal, git-filter, cancel, and error paths, so the returned path
|
|
150
|
+
always points at a complete file.
|
|
151
|
+
- Fixed the context-GC auto-digest (a machine paraphrase of possibly attacker-influenced tool output)
|
|
152
|
+
being inlined into the prompt as bare prose: it is now wrapped in the standard untrusted-content
|
|
153
|
+
fence, the same boundary memory recall pages use, so an injection payload in the digest is framed as
|
|
154
|
+
data, not instructions.
|
|
155
|
+
- Fixed profile-denied context files (AGENTS.md/CLAUDE.md/GEMINI.md) being read and processed as
|
|
156
|
+
content before the agents-kind profile filter: the loader now reads each candidate file's raw bytes
|
|
157
|
+
once purely to discover any embedded `<resource-profile>` blocks (unavoidable — a profile can be
|
|
158
|
+
defined in a file it then denies), and only sanitizes, threat-scans, and exposes files the profile
|
|
159
|
+
allows. A denied file's instructional content is never loaded into the session, and the redundant
|
|
160
|
+
double read of every context file is gone.
|
|
161
|
+
- Fixed the profile resource editor silently widening a closed grant to a wildcard: when every id in a
|
|
162
|
+
kind's (possibly collapsed) universe was enabled, a no-change save re-encoded an enumerated grant
|
|
163
|
+
like `{allow:[alpha,beta]}` as `{allow:["*"]}`, auto-granting every future resource of that kind. The
|
|
164
|
+
save now preserves the enumerated list and only keeps `["*"]` when the grant was already a wildcard
|
|
165
|
+
(or grant-all was chosen explicitly).
|
|
166
|
+
- Fixed skills, prompts, and extensions denied by the active resource profile being silently absent
|
|
167
|
+
from `/context`: it now reports "N skill(s)/prompt(s)/extension(s) withheld by the active resource
|
|
168
|
+
profile — grant the <kind> kind to restore them", the same visibility the withheld-AGENTS.md
|
|
169
|
+
warning already gave context files.
|
|
170
|
+
- Fixed a silently-swallowed executor miss: when an executor-routed turn ran no toolkit command and
|
|
171
|
+
the reflex brain could not refine the request into an explicit instruction, the turn ended with no
|
|
172
|
+
retry and no explanation. It now surfaces a warning that the command did not run and no automatic
|
|
173
|
+
escalation happened (the no-frontier-fallback policy is unchanged).
|
|
174
|
+
- Fixed router-swapped turns (G4) leaving the system prompt at the full tool surface: when a turn is
|
|
175
|
+
routed to a smaller model its tool set is filtered, but the system prompt still carried guidelines
|
|
176
|
+
and schemas for tools the routed model couldn't call — billed every request and confusing to a
|
|
177
|
+
cheap/local model. The prompt is now rebuilt for the routed model's filtered surface and restored
|
|
178
|
+
afterwards, including when the routed run throws.
|
|
179
|
+
- Fixed the learning gate's contradiction branch being unreachable dead code: the reflection call site
|
|
180
|
+
hardcoded `contradictions: 0`, so a durable `memory_replace`/`memory_remove` — which overwrites or
|
|
181
|
+
deletes an existing memory fact (the reflection engine's confront-before-write conflict signal) —
|
|
182
|
+
could auto-apply and silently destroy prior knowledge. Such supersessions now route through the
|
|
183
|
+
contradiction branch (approval-gated proposal, audited); purely additive writes are unaffected.
|
|
184
|
+
- Fixed a learning-policy cliff where enabling the policy with stock settings silently disabled
|
|
185
|
+
learning entirely: a below-confidence-threshold cue with no evidence returned a silent no-op
|
|
186
|
+
(reflectionSourceConfidence 50 < confidenceThreshold 90, reflection writes carry no evidence), so
|
|
187
|
+
every durable write was dropped with no apply and no audit trail. Below-threshold cues now degrade
|
|
188
|
+
to an approval-gated proposal that is audited and visible in `/autonomy diagnostics`, while staying
|
|
189
|
+
fail-closed — nothing auto-applies below the threshold.
|
|
190
|
+
|
|
191
|
+
## [0.80.100] - 2026-07-02
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- Added `/models suggest`: a curated roster of local models validated during pi's own small-model
|
|
196
|
+
research, each with the role it was shaped for — qwen3:1.7b as the toolkit executor/reflex
|
|
197
|
+
muscle, qwen3:0.6b as a minimal fast executor, and the Ternary-Bonsai family (1.7B search scout,
|
|
198
|
+
4B context-curator/reflex-brain, 8B routing-judge for larger machines) marked as non-tool-calling
|
|
199
|
+
lane/brain models. Each suggestion is a ready `/models add` ref; the roster is surfaced when no
|
|
200
|
+
local models are installed. No per-model score is baked in — fitness is host-dependent, so
|
|
201
|
+
`/models add` still auto-probes on the actual machine and the roster only encodes each model's
|
|
202
|
+
validated role.
|
|
203
|
+
|
|
1
204
|
## [0.80.99] - 2026-07-02
|
|
2
205
|
|
|
3
206
|
### Added
|
|
@@ -29,6 +29,7 @@ import { type CustomMessage } from "./messages.ts";
|
|
|
29
29
|
import { type ModelCapabilityProfile } from "./model-capability.ts";
|
|
30
30
|
import type { ModelRegistry } from "./model-registry.ts";
|
|
31
31
|
import { type StoredFitnessReport } from "./models/fitness-store.ts";
|
|
32
|
+
import { type LocalRuntimeDeps, OllamaRuntime } from "./models/local-runtime.ts";
|
|
32
33
|
import { type PromptTemplate } from "./prompt-templates.ts";
|
|
33
34
|
import { type ModelFitnessReport } from "./research/model-fitness.ts";
|
|
34
35
|
import { type ResearchRunResult } from "./research/research-runner.ts";
|
|
@@ -91,6 +92,10 @@ export type AgentSessionEvent = Exclude<AgentEvent, {
|
|
|
91
92
|
success: boolean;
|
|
92
93
|
attempt: number;
|
|
93
94
|
finalError?: string;
|
|
95
|
+
} | {
|
|
96
|
+
type: "routing_start";
|
|
97
|
+
} | {
|
|
98
|
+
type: "routing_end";
|
|
94
99
|
};
|
|
95
100
|
/** Listener function for agent session events */
|
|
96
101
|
export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
|
|
@@ -148,6 +153,12 @@ export interface AgentSessionConfig {
|
|
|
148
153
|
* defaults to the real, best-effort collector.
|
|
149
154
|
*/
|
|
150
155
|
collectWorkspaceSources?: typeof collectWorkspaceSources;
|
|
156
|
+
/**
|
|
157
|
+
* Injected fetch/spawn/exists for the local (Ollama) runtime health-check + boot used by the
|
|
158
|
+
* model router before a turn routed to a local model (see _ensureLocalModelReady). Unit tests
|
|
159
|
+
* inject fakes so they never hit a real network/process; production defaults to the real ones.
|
|
160
|
+
*/
|
|
161
|
+
localRuntimeDeps?: LocalRuntimeDeps;
|
|
151
162
|
}
|
|
152
163
|
export interface ExtensionBindings {
|
|
153
164
|
uiContext?: ExtensionUIContext;
|
|
@@ -345,6 +356,8 @@ export declare class AgentSession {
|
|
|
345
356
|
private readonly _brainCurator;
|
|
346
357
|
private _lastCurationSkipReason;
|
|
347
358
|
private _inertExtensionWarnings;
|
|
359
|
+
/** Extensions the active resource profile removed from the runtime set (surfaced in /context). */
|
|
360
|
+
private _profileDeniedExtensionCount;
|
|
348
361
|
private _lastPreDigestSkipReason;
|
|
349
362
|
private _unboundToolGrantWarnings;
|
|
350
363
|
private _toolArtifactStore;
|
|
@@ -370,6 +383,12 @@ export declare class AgentSession {
|
|
|
370
383
|
private _cwd;
|
|
371
384
|
private _agentDir;
|
|
372
385
|
private _collectWorkspaceSources;
|
|
386
|
+
private _localRuntimeDeps?;
|
|
387
|
+
/** Lazy, cached by baseUrl so the router path and any other caller share one instance per server. */
|
|
388
|
+
private _localRuntimes;
|
|
389
|
+
/** Server URLs confirmed reachable THIS session — skips the health-check round trip on every
|
|
390
|
+
* local-routed turn once warm. Keyed the same way as _localRuntimes. */
|
|
391
|
+
private _localRuntimeConfirmedUp;
|
|
373
392
|
private _extensionRunnerRef?;
|
|
374
393
|
private _initialActiveToolNames?;
|
|
375
394
|
private _allowedToolNames?;
|
|
@@ -673,6 +692,16 @@ export declare class AgentSession {
|
|
|
673
692
|
private _emit;
|
|
674
693
|
private _emitQueueUpdate;
|
|
675
694
|
private _lastAssistantMessage;
|
|
695
|
+
/**
|
|
696
|
+
* User messages already painted to the UI by an early, synthetic `message_start` fired from
|
|
697
|
+
* `_promptUnserialized` — before the model-router judge's bounded LLM call — so the prompt
|
|
698
|
+
* appears immediately instead of hanging until routing finishes. The real agent-loop run emits
|
|
699
|
+
* its own authoritative `message_start` for the SAME message object once the turn actually
|
|
700
|
+
* starts; `_handleAgentEvent` consumes (deletes) it from this set to suppress that one duplicate
|
|
701
|
+
* listener notification. Persistence is untouched: it stays keyed off `message_end`, which is
|
|
702
|
+
* never added here and never suppressed.
|
|
703
|
+
*/
|
|
704
|
+
private _earlyDisplayedUserMessages;
|
|
676
705
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
677
706
|
private _handleAgentEvent;
|
|
678
707
|
private _willRetryAfterAgentEnd;
|
|
@@ -797,13 +826,41 @@ export declare class AgentSession {
|
|
|
797
826
|
private _buildSituationSoulPrompt;
|
|
798
827
|
private _buildSelfModificationPrompt;
|
|
799
828
|
private _buildAutonomyPrompt;
|
|
829
|
+
private _buildSystemPromptOptionsForToolNames;
|
|
800
830
|
private _rebuildSystemPrompt;
|
|
831
|
+
/**
|
|
832
|
+
* Build a system prompt for a specific tool surface WITHOUT touching the session's base prompt
|
|
833
|
+
* state. Used for a router-swapped turn (G4): the routed model runs against a filtered tool set,
|
|
834
|
+
* so it must also receive a system prompt whose tool guidelines/snippets match that filtered
|
|
835
|
+
* surface — but the change is per-turn, so it must not mutate `_baseSystemPromptOptions` (which
|
|
836
|
+
* later turns and extension events read).
|
|
837
|
+
*/
|
|
838
|
+
private _buildSystemPromptForToolNames;
|
|
801
839
|
private _runAgentPrompt;
|
|
802
840
|
private _isModelAvailableAndAuthed;
|
|
803
841
|
private _resolveExecutorRoute;
|
|
804
842
|
/** True if a run_toolkit_script tool result since `fromIndex` actually EXECUTED (not error/ambiguous). */
|
|
805
843
|
private _executorTurnExecutedScript;
|
|
806
844
|
private _buildExecutorRefinedPrompt;
|
|
845
|
+
/**
|
|
846
|
+
* Shared {@link OllamaRuntime} for a given server, lazily created and cached by baseUrl so every
|
|
847
|
+
* caller — the router's readiness gate below and any host UI's own model-lifecycle commands
|
|
848
|
+
* (e.g. `/models`) — sees and can stop the SAME pi-managed process instead of each tracking its
|
|
849
|
+
* own untracked child.
|
|
850
|
+
*/
|
|
851
|
+
getLocalRuntime(baseUrl?: string): OllamaRuntime;
|
|
852
|
+
/** models.json registers a local model's baseUrl as `<server>/v1` (OpenAI-compat); the runtime's
|
|
853
|
+
* own health/boot endpoints are on the Ollama-native server root. */
|
|
854
|
+
private _deriveOllamaServerUrl;
|
|
855
|
+
/**
|
|
856
|
+
* If the last assistant message in this session was an error from THIS exact local server, a
|
|
857
|
+
* cached "confirmed up" flag would be stale (the server may have died mid-session) — drop it so
|
|
858
|
+
* the next ensure-check is a real one instead of trusting stale state.
|
|
859
|
+
*/
|
|
860
|
+
private _invalidateLocalRuntimeIfLastCallFailed;
|
|
861
|
+
private _ensureLocalModelReady;
|
|
862
|
+
private _maybeInstallOllamaOnConsent;
|
|
863
|
+
private _ensureRouteModelReady;
|
|
807
864
|
private _resolveModelRouterTurnRoute;
|
|
808
865
|
private _resolveModelRouterModelForIntent;
|
|
809
866
|
private _resolveConfiguredTierModel;
|
|
@@ -1021,6 +1078,21 @@ export declare class AgentSession {
|
|
|
1021
1078
|
private _isToolOrCommandAllowedByProfile;
|
|
1022
1079
|
private _hasToolOrCommandProfileGate;
|
|
1023
1080
|
private _filterExtensionsForRuntime;
|
|
1081
|
+
/**
|
|
1082
|
+
* /context observations for skills/prompts/extensions the active resource profile removed from
|
|
1083
|
+
* listings — the analog of the withheld-AGENTS.md warning. Strict UAC makes these silently absent,
|
|
1084
|
+
* so a lean profile's effect on the resource surface stays visible. Counts are profile-scoped
|
|
1085
|
+
* (skills/prompts via the profile-independent discovery universe filtered by the live profile
|
|
1086
|
+
* filter; extensions via the runtime filter's denied tally). Empty when nothing is withheld.
|
|
1087
|
+
*
|
|
1088
|
+
* Uses `isResourceDeniedByActiveProfile` (profile-only), not `isResourceAllowedByProfile` (which
|
|
1089
|
+
* also folds in the user's own legacy `disabledResources` list): a plain user-disabled resource
|
|
1090
|
+
* must never be misattributed to "the active resource profile" — that case is already surfaced by
|
|
1091
|
+
* the G14 disable-wins warning. With no active profile at all, the helper always reports nothing
|
|
1092
|
+
* denied, so this naturally stays silent (extensions keep their own runtime-filter-derived count,
|
|
1093
|
+
* which is already correctly zero absent a profile).
|
|
1094
|
+
*/
|
|
1095
|
+
private _profileDeniedResourceObservations;
|
|
1024
1096
|
private _reapplyActiveProfileModelSettings;
|
|
1025
1097
|
private _initializeMemory;
|
|
1026
1098
|
/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */
|