Skip to content

feat(dsh): add opt-in long-term memory for dsh-pet - #2608

Open
knqiufan wants to merge 6 commits into
masterfrom
codex/dsh-pet-memory-2606
Open

knqiufan wants to merge 6 commits into
masterfrom
codex/dsh-pet-memory-2606

Conversation

@knqiufan

@knqiufan knqiufan commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Which issue or RFC does this PR close?

Closes #2606. Refs #2272.

Rationale for this change

dsh-pet keeps local chat history, but older preferences stop reaching the model once they fall outside its recent window. An optional host adapter lets the pet use long-term memory from an existing PowerContext Server without requiring changes to dsh-pet or starting a Server on its behalf.

What changes are included in this PR?

  • Add the standalone powercontext-dsh-pet Host package for DSH Web and Desktop. It uses dsh-pet's existing memory slot, leaves other providers in place, and searches active Atomic Memory in the exact Scope selected for each pet.
  • Store eligible completed text exchanges in a private bounded queue. Check the configured Server and authenticated identity before delivery, and retry uncertain responses with the same Source ID and payload. Source acceptance and Memory extraction remain separate.
  • Add guided terminal opt-in, explicit per-pet Scope bindings for unattended setup, separate diagnostics, and off/discard controls. Web and Desktop keep separate bindings and queues. The Desktop setup path uses the installed application's CLI and reserved profile. Ship an install-verified archive and bilingual guides.

Are there any user-facing changes?

Pet memory is off by default. The tested combination is DSH 0.2.2-rc.1, dsh-pet 0.4.8, and a matching adapter and Server build. Desktop acceptance used the installed macOS arm64 app. When the selected profile has a compatible dsh-pet enabled, interactive powercontext setup dsh offers first-time opt-in and lets the user select an existing Scope on the configured Server. Setup keeps the existing dsh-pet and installs only the memory adapter after verification. Unattended and JSON setup require --dsh-pet-memory on and --dsh-pet-bind PET_ID=SCOPE_ID to enable memory. Standalone pets do not use the adapter. No Server API changes.

How was this change tested?

  • make check, make js-test, make docs-test, and the focused DSH CLI/profile/transport suite (94 passed, 50 optional fixture cases skipped).
  • Real Web and installed Desktop: make dsh-pet-runtime-test, with DSH_PET_TEST_DESKTOP_APP set for the macOS app. Used isolated profiles, the official dsh-pet, the packed adapter, and a real PowerContext Server. Verified setup/doctor, capture and extraction, recall after Host restart, Scope reference isolation, chat during an unavailable Server route, idempotent replay after a lost response, and disabling the provider.
  • Verified the guided opt-in in a real terminal on Web and installed macOS Desktop with isolated profiles and a real Server: ordinary JSON setup left the adapter uninstalled, while interactive setup listed Scopes, installed the adapter, and persisted the exact selected binding.
  • Local Desktop co-test with feat(dsh): embed existing Dashboard in right sidebar #2589 at deb7dacc. Installed the combined build in an isolated profile and explicitly selected the same Scope for the test conversation and pet. The existing Dashboard opened inside the Desktop right Browser webview; its Memory page showed the extracted preference and the associated dsh-pet: Source. The Dashboard still follows the selected conversation's Scope. The feat(dsh): embed existing Dashboard in right sidebar #2589 changes are not part of this PR.
  • In the synthetic replay, native recent history returned no preference in 3/3 probes; PowerContext with the same recent window and the full-history control returned the corrected preference in 3/3 probes on both hosts. The deterministic local model fixture verifies context delivery; real model quality, usage, and billing were not measured.

AI usage statement

OpenAI Codex (GPT-6) helped implement, review, test, and document this change.

@hidb4ai hidb4ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new CLI diagnostic field breaks the existing Desktop integrations diagnostic projection, including when pet memory is off. Please keep the Desktop consumer compatible with this output change.

if host == "dsh":
from powercontext.cli.dsh_pet import pet_memory_diagnostic

checks["dsh_pet_memory"] = pet_memory_diagnostic(options["dsh_target"])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Keep Desktop diagnostics compatible with the new check

This adds dsh_pet_memory to every DSH doctor result, even when DSH is not installed and pet memory is off. However, desktop/src-tauri/src/diagnostics.rs::project rejects any check name outside its allowlist, which does not include this field. As Desktop always includes DSH in its integrations diagnostic command, the entire report now fails with InvalidResponse. I reproduced this with actual powercontext doctor dsh --json output: the base output passes the unchanged Rust projection, while this head fails. The Linux and Windows CI jobs also fail at diagnostic_cli_probe.rs:82 with real integrations projection: InvalidResponse. Please update the Desktop diagnostic consumer alongside the CLI field and cover the real CLI-to-Desktop path, including the default-off case.

@hireview001 hireview001 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • CI failed: CI result (failure).
  • CI failed: desktop-validation / linux (failure).
  • CI failed: desktop-validation / windows (failure).
  • CI failed: Main (failure). Failed steps: desktop-validation / windows / Test native diagnostics with isolated real CLI; desktop-validation / linux / Test native diagnostics with isolated real Linux CLI; CI result / Require successful selected checks.

async function connectedClient(target: Settings, signal: AbortSignal) {
if (!current(target, signal)) return
const auth = authorization(target)
if ((auth !== undefined) !== (target.identity.authentication === 'authenticated')) throw new IdentityChanged()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Align setup and runtime credential validation

When a URL-bound credential is stored for a loopback Server with authentication disabled, setup accepts the binding, but this guard rejects every recall and queued delivery before checking the Server's identity. Align setup and runtime validation so a binding reported as enabled can actually operate.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(dsh): add opt-in long-term memory for dsh-pet

3 participants