@pi-unipi/unipi 3.0.0-alpha.2 → 3.0.0-alpha.21
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 +292 -0
- package/README.md +8 -11
- package/docs/prefix-cache-architecture.md +14 -0
- package/package.json +22 -24
- package/packages/ask-user/README.md +55 -107
- package/packages/ask-user/ask-ui.ts +306 -732
- package/packages/ask-user/clipboard.ts +50 -0
- package/packages/ask-user/config.ts +74 -78
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/questions.ts +151 -0
- package/packages/ask-user/skills/ask-user/SKILL.md +59 -133
- package/packages/ask-user/tools.ts +198 -432
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +38 -43
- package/packages/autocomplete/src/sorting.ts +8 -0
- package/packages/background-tasks/package.json +2 -2
- package/packages/background-tasks/src/config.ts +0 -73
- package/packages/background-tasks/src/index.ts +20 -16
- package/packages/background-tasks/src/registry.ts +1 -171
- package/packages/background-tasks/src/types.ts +0 -32
- package/packages/btw/README.md +13 -56
- package/packages/btw/extensions/btw.ts +403 -1796
- package/packages/btw/package.json +5 -2
- package/packages/btw/skills/btw/SKILL.md +7 -143
- package/packages/compactor/README.md +56 -287
- package/packages/compactor/package.json +5 -9
- package/packages/compactor/skills/compactor/SKILL.md +13 -20
- package/packages/compactor/src/card.ts +90 -0
- package/packages/compactor/src/commands/index.ts +73 -130
- package/packages/compactor/src/compaction/compact-args.ts +5 -3
- package/packages/compactor/src/compaction/filter-noise.ts +1 -1
- package/packages/compactor/src/compaction/hooks.ts +487 -311
- package/packages/compactor/src/compaction/source.ts +178 -0
- package/packages/compactor/src/compaction/summarize.ts +586 -52
- package/packages/compactor/src/config/manager.ts +130 -127
- package/packages/compactor/src/config/schema.ts +32 -48
- package/packages/compactor/src/index.ts +40 -431
- package/packages/compactor/src/info-screen.ts +44 -190
- package/packages/compactor/src/session/recall-blocks.ts +1 -1
- package/packages/compactor/src/stats.ts +76 -0
- package/packages/compactor/src/tools/context-budget.ts +17 -34
- package/packages/compactor/src/tools/ctx-doctor.ts +45 -36
- package/packages/compactor/src/tools/register.ts +29 -269
- package/packages/compactor/src/types.ts +47 -186
- package/packages/core/README.md +25 -0
- package/packages/core/child-agent.ts +1 -0
- package/packages/core/command-echo.ts +63 -0
- package/packages/core/compaction-context.ts +41 -0
- package/packages/core/constants.ts +8 -38
- package/packages/core/events.ts +0 -53
- package/packages/core/fusion-status.ts +4 -0
- package/packages/core/global.d.ts +10 -0
- package/packages/core/harness-messages.ts +392 -0
- package/packages/core/index.ts +14 -0
- package/packages/core/kanboard-status.ts +49 -0
- package/packages/core/long-horizon-owner-status.ts +46 -0
- package/packages/core/model-cache.ts +81 -7
- package/packages/core/package.json +6 -3
- package/packages/core/src/attach/detect.ts +163 -0
- package/packages/core/src/child-agent/child-args.ts +31 -0
- package/packages/core/src/child-agent/delivery.ts +41 -0
- package/packages/core/src/child-agent/index.ts +5 -0
- package/packages/core/src/child-agent/readers.ts +203 -0
- package/packages/core/src/child-agent/runtime.ts +584 -0
- package/packages/core/src/evidence.ts +78 -0
- package/packages/core/src/hints/browser.ts +278 -0
- package/packages/core/src/hints/crab-data.ts +19 -0
- package/packages/core/src/hints/index.ts +865 -0
- package/packages/core/src/hints/lines.ts +607 -0
- package/packages/core/src/hints/store.ts +120 -0
- package/packages/core/src/jev/chatter.ts +24 -0
- package/packages/core/src/jev/settings.ts +177 -14
- package/packages/core/src/package-colors.ts +2 -0
- package/packages/core/src/settings/catalog.ts +39 -15
- package/packages/core/src/settings/engine.ts +48 -2
- package/packages/core/src/settings/hub.ts +83 -20
- package/packages/core/src/settings/open.ts +49 -0
- package/packages/core/src/settings/schema.ts +27 -7
- package/packages/core/src/tui/hub-kit.ts +18 -5
- package/packages/core/src/tui/kit.ts +198 -0
- package/packages/core/src/tui/progress.ts +73 -0
- package/packages/core/src/turn/arbiter.ts +290 -0
- package/packages/footer/README.md +4 -6
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/glance-editor.ts +19 -11
- package/packages/footer/src/help.ts +1 -1
- package/packages/footer/src/index.ts +36 -3
- package/packages/footer/src/presets.ts +3 -4
- package/packages/footer/src/rendering/icons.ts +0 -20
- package/packages/footer/src/segments/compactor.ts +52 -142
- package/packages/footer/src/segments/status-ext.ts +0 -1
- package/packages/fusion/README.md +14 -4
- package/packages/fusion/package.json +4 -3
- package/packages/fusion/src/child-args.ts +1 -0
- package/packages/fusion/src/index.ts +161 -8
- package/packages/fusion/src/pi-settings.ts +57 -0
- package/packages/fusion/src/picker.ts +186 -51
- package/packages/fusion/src/preset.ts +56 -2
- package/packages/fusion/src/prompts.ts +1 -1
- package/packages/fusion/src/sidekick-runtime.ts +1 -420
- package/packages/fusion/src/tools.ts +107 -128
- package/packages/fusion/src/transcript.ts +27 -85
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/README.md +18 -30
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/input-shortcuts/src/burst.ts +88 -0
- package/packages/input-shortcuts/src/chord-overlay.ts +20 -70
- package/packages/input-shortcuts/src/cleared-input.ts +97 -0
- package/packages/input-shortcuts/src/index.ts +99 -193
- package/packages/input-shortcuts/src/last-response.ts +40 -0
- package/packages/input-shortcuts/src/registers.ts +8 -23
- package/packages/input-shortcuts/src/types.ts +4 -16
- package/packages/input-shortcuts/src/undo-redo.ts +59 -47
- package/packages/kanboard/README.md +51 -47
- package/packages/kanboard/index.ts +293 -55
- package/packages/kanboard/package.json +8 -8
- package/packages/kanboard/skills/kanboard/SKILL.md +61 -27
- package/packages/kanboard/src/badges.ts +93 -0
- package/packages/kanboard/src/bin.ts +4 -2
- package/packages/kanboard/src/commands.ts +218 -84
- package/packages/kanboard/src/debug.ts +20 -0
- package/packages/kanboard/src/guard.ts +267 -109
- package/packages/kanboard/src/monitor.ts +330 -0
- package/packages/kanboard/src/notice-buffer.ts +74 -0
- package/packages/kanboard/src/progress.ts +27 -0
- package/packages/kanboard/src/reminders.ts +234 -0
- package/packages/kanboard/src/settings.ts +69 -15
- package/packages/kanboard/src/shapes.ts +5 -0
- package/packages/long-horizon/index.ts +190 -13
- package/packages/long-horizon/package.json +3 -3
- package/packages/long-horizon/src/commands.ts +103 -7
- package/packages/long-horizon/src/compaction-brief.ts +35 -0
- package/packages/long-horizon/src/engine/continuation.ts +84 -15
- package/packages/long-horizon/src/engine/goal-state.ts +64 -13
- package/packages/long-horizon/src/engine/nudge-stash.ts +71 -0
- package/packages/long-horizon/src/engine/ralph.ts +3 -2
- package/packages/long-horizon/src/engine/runaway.ts +68 -11
- package/packages/long-horizon/src/engine/verifier.ts +19 -0
- package/packages/long-horizon/src/gate.ts +37 -12
- package/packages/long-horizon/src/judge/resolve.ts +1 -0
- package/packages/long-horizon/src/owner.ts +35 -2
- package/packages/long-horizon/src/progress.ts +87 -0
- package/packages/long-horizon/src/prompts/goal.ts +1 -1
- package/packages/long-horizon/src/runtime.ts +172 -18
- package/packages/long-horizon/src/settings.ts +54 -39
- package/packages/long-horizon/src/tools/goal.ts +6 -0
- package/packages/long-horizon/src/tools/graph.ts +1 -1
- package/packages/long-horizon/src/tools/swarm.ts +3 -3
- package/packages/mcp/package.json +2 -2
- package/packages/memory/commands.ts +7 -2
- package/packages/memory/index.ts +210 -32
- package/packages/memory/package.json +3 -3
- package/packages/memory/save-session.ts +264 -0
- package/packages/memory/settings.ts +17 -0
- package/packages/memory/tools.ts +253 -203
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/README.md +53 -16
- package/packages/skill-registry/index.ts +230 -0
- package/packages/skill-registry/package.json +19 -8
- package/packages/skill-registry/src/editor.ts +206 -0
- package/packages/skill-registry/src/judge.ts +289 -0
- package/packages/skill-registry/src/registry.ts +87 -0
- package/packages/skill-registry/src/settings.ts +259 -0
- package/packages/skill-registry/src/vault.ts +80 -0
- package/packages/subagents/README.md +39 -119
- package/packages/subagents/package.json +6 -13
- package/packages/subagents/skills/subagents/SKILL.md +18 -42
- package/packages/subagents/src/agents.ts +213 -0
- package/packages/subagents/src/cards.ts +182 -0
- package/packages/subagents/src/index.ts +609 -1084
- package/packages/subagents/src/manager.ts +429 -0
- package/packages/subagents/src/profiles.ts +130 -0
- package/packages/subagents/src/transcript.ts +154 -0
- package/packages/subagents/src/ui.ts +389 -0
- package/packages/unipi/bundled.js +39756 -45569
- package/packages/unipi/index.ts +55 -10
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +76 -69
- package/packages/utility/package.json +2 -2
- package/packages/utility/skills/image/SKILL.md +37 -0
- package/packages/utility/skills/utility/SKILL.md +17 -60
- package/packages/utility/src/answer/extract.ts +128 -0
- package/packages/utility/src/answer/index.ts +213 -0
- package/packages/utility/src/answer/reply.ts +133 -0
- package/packages/utility/src/answer/web.ts +167 -0
- package/packages/utility/src/attach/index.ts +205 -0
- package/packages/utility/src/commands.ts +38 -142
- package/packages/utility/src/diagnostics/engine.ts +50 -5
- package/packages/utility/src/image/index.ts +33 -0
- package/packages/utility/src/image/models.ts +221 -0
- package/packages/{image/src → utility/src/image}/recognize.ts +2 -2
- package/packages/utility/src/image/settings.ts +178 -0
- package/packages/{image/src/image-source.ts → utility/src/image/source.ts} +1 -1
- package/packages/utility/src/image/tools.ts +168 -0
- package/packages/utility/src/image/transports.ts +186 -0
- package/packages/utility/src/index.ts +68 -389
- package/packages/utility/src/lifecycle/cleanup.ts +116 -311
- package/packages/utility/src/rename/gate.ts +102 -0
- package/packages/utility/src/rename/index.ts +191 -0
- package/packages/utility/src/rename/session.ts +170 -0
- package/packages/utility/src/render/delegated.ts +285 -0
- package/packages/utility/src/render/harness.ts +683 -0
- package/packages/utility/src/render/parse.ts +156 -0
- package/packages/utility/src/render/pi-settings.ts +38 -0
- package/packages/utility/src/render/reply-bg.ts +307 -0
- package/packages/utility/src/render/simple.ts +724 -0
- package/packages/utility/src/render/spacing.ts +235 -0
- package/packages/utility/src/render/styled.ts +251 -0
- package/packages/utility/src/render/tools.ts +353 -0
- package/packages/utility/src/settings.ts +166 -233
- package/packages/utility/src/types.ts +1 -222
- package/packages/watchdog/index.ts +17 -6
- package/packages/watchdog/package.json +3 -3
- package/packages/watchdog/src/config.ts +3 -2
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/README.md +3 -0
- package/packages/workflow/index.ts +0 -2
- package/packages/workflow/package.json +2 -2
- package/packages/workflow/src/permission/decide.ts +6 -4
- package/packages/workflow/src/permission/index.ts +17 -7
- package/packages/workflow/src/permission/settings.ts +39 -4
- package/packages/workflow/src/plan/index.ts +19 -4
- package/packages/background-tasks/extensions/delegate-child.ts +0 -1
- package/packages/background-tasks/src/context-parent-snapshot.ts +0 -142
- package/packages/background-tasks/src/context-token-budget.ts +0 -903
- package/packages/background-tasks/src/context-visible-conversation-v2.ts +0 -551
- package/packages/background-tasks/src/delegate/artifacts.ts +0 -487
- package/packages/background-tasks/src/delegate/budget.ts +0 -415
- package/packages/background-tasks/src/delegate/hook-contract-evidence.json +0 -18
- package/packages/background-tasks/src/delegate/hook-contract.ts +0 -154
- package/packages/background-tasks/src/delegate/launch.ts +0 -484
- package/packages/background-tasks/src/delegate/result-package.ts +0 -459
- package/packages/background-tasks/src/delegate/runner.ts +0 -430
- package/packages/background-tasks/src/delegate/seed.ts +0 -423
- package/packages/background-tasks/src/delegate/types.ts +0 -323
- package/packages/background-tasks/src/delegate-child-extension.ts +0 -978
- package/packages/background-tasks/src/delegate-extension.ts +0 -654
- package/packages/background-tasks/src/fixtures/delegate-context-incident.json +0 -17
- package/packages/compactor/skills/compactor-detail/SKILL.md +0 -116
- package/packages/compactor/skills/compactor-doctor/SKILL.md +0 -71
- package/packages/compactor/skills/compactor-stats/SKILL.md +0 -51
- package/packages/compactor/src/compaction/build-sections.ts +0 -76
- package/packages/compactor/src/compaction/extract/goals.ts +0 -36
- package/packages/compactor/src/compaction/extract/preferences.ts +0 -40
- package/packages/compactor/src/compaction/format.ts +0 -53
- package/packages/compactor/src/compaction/merge.ts +0 -143
- package/packages/compactor/src/config/presets.ts +0 -160
- package/packages/compactor/src/executor/executor.ts +0 -233
- package/packages/compactor/src/executor/runtime.ts +0 -115
- package/packages/compactor/src/security/evaluator.ts +0 -89
- package/packages/compactor/src/security/policy.ts +0 -96
- package/packages/compactor/src/security/scanner.ts +0 -65
- package/packages/compactor/src/session/auto-inject.ts +0 -60
- package/packages/compactor/src/session/db.ts +0 -325
- package/packages/compactor/src/session/extract.ts +0 -144
- package/packages/compactor/src/session/resume-inject.ts +0 -64
- package/packages/compactor/src/session/snapshot.ts +0 -327
- package/packages/compactor/src/tools/ctx-batch-execute.ts +0 -41
- package/packages/compactor/src/tools/ctx-execute-file.ts +0 -23
- package/packages/compactor/src/tools/ctx-execute.ts +0 -23
- package/packages/compactor/src/tools/ctx-stats.ts +0 -96
- package/packages/image/README.md +0 -99
- package/packages/image/package.json +0 -61
- package/packages/image/skills/image/SKILL.md +0 -76
- package/packages/image/src/generate.ts +0 -256
- package/packages/image/src/index.ts +0 -135
- package/packages/image/src/models.ts +0 -519
- package/packages/image/src/openai-images-api.ts +0 -282
- package/packages/image/src/register-providers.ts +0 -209
- package/packages/image/src/settings.ts +0 -173
- package/packages/image/src/tools.ts +0 -326
- package/packages/input-shortcuts/src/clipboard.ts +0 -119
- package/packages/kanboard/src/runner.ts +0 -817
- package/packages/skill-registry/skills/auto/SKILL.md +0 -465
- package/packages/skill-registry/skills/brainstorm/SKILL.md +0 -219
- package/packages/skill-registry/skills/chore-create/SKILL.md +0 -315
- package/packages/skill-registry/skills/chore-execute/SKILL.md +0 -314
- package/packages/skill-registry/skills/consolidate/SKILL.md +0 -142
- package/packages/skill-registry/skills/consultant/SKILL.md +0 -97
- package/packages/skill-registry/skills/debug/SKILL.md +0 -228
- package/packages/skill-registry/skills/document/SKILL.md +0 -120
- package/packages/skill-registry/skills/fix/SKILL.md +0 -212
- package/packages/skill-registry/skills/gather-context/SKILL.md +0 -145
- package/packages/skill-registry/skills/plan/SKILL.md +0 -231
- package/packages/skill-registry/skills/quick-fix/SKILL.md +0 -135
- package/packages/skill-registry/skills/quick-work/SKILL.md +0 -110
- package/packages/skill-registry/skills/research/SKILL.md +0 -251
- package/packages/skill-registry/skills/review-work/SKILL.md +0 -187
- package/packages/skill-registry/skills/scan-issues/SKILL.md +0 -195
- package/packages/skill-registry/skills/work/SKILL.md +0 -218
- package/packages/skill-registry/skills/worktree-create/SKILL.md +0 -69
- package/packages/skill-registry/skills/worktree-list/SKILL.md +0 -78
- package/packages/skill-registry/skills/worktree-merge/SKILL.md +0 -89
- package/packages/subagents/agents/delegate.md +0 -14
- package/packages/subagents/agents/oracle.md +0 -78
- package/packages/subagents/agents/researcher.md +0 -52
- package/packages/subagents/agents/reviewer.md +0 -80
- package/packages/subagents/agents/scout.md +0 -50
- package/packages/subagents/agents/worker.md +0 -59
- package/packages/subagents/prompts/council.md +0 -48
- package/packages/subagents/prompts/gather-context-and-clarify.md +0 -13
- package/packages/subagents/prompts/parallel-cleanup.md +0 -59
- package/packages/subagents/prompts/parallel-research.md +0 -50
- package/packages/subagents/prompts/parallel-review.md +0 -54
- package/packages/subagents/prompts/review-loop.md +0 -43
- package/packages/subagents/skills/council-mode/SKILL.md +0 -230
- package/packages/subagents/skills/subagents/references/constraints-and-recipes.md +0 -259
- package/packages/subagents/skills/subagents/references/execution-controls.md +0 -454
- package/packages/subagents/skills/subagents/references/management-authoring-rpc.md +0 -161
- package/packages/subagents/skills/subagents/references/multi-lane-orchestration.md +0 -39
- package/packages/subagents/skills/subagents/references/prompting-and-roles.md +0 -267
- package/packages/subagents/src/acceptance.ts +0 -331
- package/packages/subagents/src/agent-manager.ts +0 -405
- package/packages/subagents/src/agent-memory.ts +0 -300
- package/packages/subagents/src/agent-overrides.ts +0 -183
- package/packages/subagents/src/agent-runner.ts +0 -271
- package/packages/subagents/src/async-runner.ts +0 -422
- package/packages/subagents/src/authority-policy.ts +0 -47
- package/packages/subagents/src/budgets.ts +0 -285
- package/packages/subagents/src/child-safety.ts +0 -140
- package/packages/subagents/src/config.ts +0 -249
- package/packages/subagents/src/conversation-viewer.ts +0 -281
- package/packages/subagents/src/core-compat.ts +0 -94
- package/packages/subagents/src/custom-agents.ts +0 -343
- package/packages/subagents/src/file-system-retry.ts +0 -50
- package/packages/subagents/src/fleet-data.ts +0 -105
- package/packages/subagents/src/fleet-view.ts +0 -322
- package/packages/subagents/src/foreground-detach.ts +0 -59
- package/packages/subagents/src/fork-context.ts +0 -285
- package/packages/subagents/src/global.d.ts +0 -7
- package/packages/subagents/src/guide.ts +0 -129
- package/packages/subagents/src/mission-state.ts +0 -133
- package/packages/subagents/src/mission-store.ts +0 -436
- package/packages/subagents/src/output-limits.ts +0 -142
- package/packages/subagents/src/parity-types.ts +0 -315
- package/packages/subagents/src/pi-args.ts +0 -167
- package/packages/subagents/src/result-files.ts +0 -232
- package/packages/subagents/src/result-watcher.ts +0 -221
- package/packages/subagents/src/retained-children.ts +0 -176
- package/packages/subagents/src/run-fanout-budget.ts +0 -356
- package/packages/subagents/src/scheduled-runs.ts +0 -349
- package/packages/subagents/src/schemas.ts +0 -263
- package/packages/subagents/src/slash-commands.ts +0 -80
- package/packages/subagents/src/supervisor-channel.ts +0 -249
- package/packages/subagents/src/tool-handler.ts +0 -1144
- package/packages/subagents/src/types.ts +0 -238
- package/packages/subagents/src/widget.ts +0 -457
- package/packages/subagents/src/workflow-script.ts +0 -737
- package/packages/subagents/src/workflow-worker.ts +0 -384
- package/packages/subagents/src/worktree.ts +0 -614
- package/packages/utility/src/analytics/collector.ts +0 -293
- package/packages/utility/src/info-screen.ts +0 -80
- package/packages/utility/src/lifecycle/process.ts +0 -162
- package/packages/utility/src/prefix-cache.ts +0 -263
- package/packages/utility/src/skill-discovery.ts +0 -542
- package/packages/utility/src/tools/env.ts +0 -113
- package/packages/utility/src/tui/name-badge-state.ts +0 -315
- package/packages/utility/src/tui/name-badge.ts +0 -109
- /package/packages/{subagents/src → core/src/child-agent}/pi-spawn.ts +0 -0
package/packages/memory/tools.ts
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Type } from "typebox";
|
|
11
|
-
import {
|
|
12
|
-
import { UNIPI_EVENTS, emitEvent } from "@pi-unipi/core";
|
|
11
|
+
import { truncateToWidth, type Component } from "@earendil-works/pi-tui";
|
|
12
|
+
import { UNIPI_EVENTS, emitEvent, meter, rail, type KitTheme } from "@pi-unipi/core";
|
|
13
13
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
14
|
-
import type { SessionBackend, SearchHit
|
|
14
|
+
import type { SessionBackend, SearchHit } from "./session.js";
|
|
15
15
|
import { findByTitle, findSimilar } from "./files.js";
|
|
16
16
|
import { MEMORY_TYPES, type MemoryType } from "./paths.js";
|
|
17
17
|
|
|
@@ -31,60 +31,54 @@ export interface ToolActivity {
|
|
|
31
31
|
onWriteDone?: () => void;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
fg: (color: string, text: string) => string;
|
|
36
|
-
bold: (text: string) => string;
|
|
37
|
-
bg?: (color: string, text: string) => string;
|
|
38
|
-
}
|
|
34
|
+
type ThemeLike = KitTheme;
|
|
39
35
|
|
|
40
|
-
/** Memory's own colour
|
|
41
|
-
const MEMORY_COLOR = "
|
|
42
|
-
const MEMORY_GLYPH = "◈";
|
|
36
|
+
/** Memory's own colour (purple) — the rail that marks every memory surface. */
|
|
37
|
+
const MEMORY_COLOR = "customMessageLabel";
|
|
43
38
|
|
|
44
39
|
export type CardTone = "memory" | "success" | "warning" | "error";
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
render(width: number): string[] {
|
|
49
|
-
return this.inner.render(Math.max(1, width - 2)).map((line) => `${this.rail} ${line}`);
|
|
50
|
-
}
|
|
51
|
-
invalidate(): void {
|
|
52
|
-
this.inner.invalidate?.();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
41
|
+
/** One rail row: left text, optional right-aligned text. */
|
|
42
|
+
export type RailRow = string | { left: string; right?: string };
|
|
55
43
|
|
|
56
|
-
/**
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
44
|
+
/**
|
|
45
|
+
* Rail card (no tinted box):
|
|
46
|
+
* ▌ Memory "subagent test UX" 5 hits · 1 project
|
|
47
|
+
* ▌ ██████▌░ pi_test_kanboard_sanity pi_test › summary · pi
|
|
48
|
+
* `tone` recolours the rail for warning/error outcomes.
|
|
49
|
+
*/
|
|
50
|
+
export function memoryCard(theme: ThemeLike, rows: RailRow[], tone: CardTone = "memory"): Component {
|
|
51
|
+
const color = tone === "warning" || tone === "error" ? tone : MEMORY_COLOR;
|
|
52
|
+
return {
|
|
53
|
+
invalidate() {},
|
|
54
|
+
render: (w: number) => rows.map((r) => truncateToWidth(typeof r === "string" ? rail(theme, color, r, "", w) : rail(theme, color, r.left, r.right ?? "", w), w)),
|
|
55
|
+
};
|
|
65
56
|
}
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
const EMPTY: Component = { invalidate() {}, render: () => [] };
|
|
59
|
+
|
|
60
|
+
/** Pending call line; disappears once the result card takes over. */
|
|
61
|
+
function pendingLine(theme: ThemeLike, context: unknown, text: string): Component {
|
|
62
|
+
if ((context as { isPartial?: boolean } | undefined)?.isPartial === false) return EMPTY;
|
|
63
|
+
return memoryCard(theme, [`${theme.bold("Memory")} ${theme.fg("dim", text)}`]);
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
function outcomeTone(outcome: unknown): CardTone {
|
|
72
67
|
return outcome === "filed" ? "success" : outcome === "queued" ? "warning" : outcome ? "error" : "memory";
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
function scoreBar(score: number): string {
|
|
76
|
-
const filled = Math.max(0, Math.min(5, Math.round(score * 5)));
|
|
77
|
-
return "▰".repeat(filled) + "▱".repeat(5 - filled);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
70
|
function outcomeLabel(outcome: string): string {
|
|
81
71
|
switch (outcome) {
|
|
82
|
-
case "filed": return "filed
|
|
83
|
-
case "queued": return "queued
|
|
84
|
-
default: return "markdown only
|
|
72
|
+
case "filed": return "✓ filed";
|
|
73
|
+
case "queued": return "⧗ queued";
|
|
74
|
+
default: return "⚠ markdown only";
|
|
85
75
|
}
|
|
86
76
|
}
|
|
87
77
|
|
|
78
|
+
function outcomeColor(outcome: string): "success" | "warning" | "error" {
|
|
79
|
+
return outcome === "filed" ? "success" : outcome === "queued" ? "warning" : "error";
|
|
80
|
+
}
|
|
81
|
+
|
|
88
82
|
function sourceLabel(raw: string): string {
|
|
89
83
|
switch (raw) {
|
|
90
84
|
case "unipi":
|
|
@@ -95,35 +89,84 @@ function sourceLabel(raw: string): string {
|
|
|
95
89
|
}
|
|
96
90
|
}
|
|
97
91
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
const plural = (n: number, word: string) => `${String(n)} ${word}${n === 1 ? "" : "s"}`;
|
|
93
|
+
|
|
94
|
+
/** `▌ Memory title ✓ filed project › type` (+ similar rows). */
|
|
95
|
+
export function storeRows(
|
|
96
|
+
t: ThemeLike,
|
|
97
|
+
d: { action?: string; title?: string; project?: string; type?: string; outcome?: string; similar?: string[] },
|
|
98
|
+
): RailRow[] {
|
|
99
|
+
const outcome = d.outcome ?? "filed";
|
|
100
|
+
return [
|
|
101
|
+
{
|
|
102
|
+
left: `${t.bold("Memory")} ${d.action === "updated" ? t.fg("dim", "updated ") : ""}${d.title ?? ""}`,
|
|
103
|
+
right: `${t.fg(outcomeColor(outcome), outcomeLabel(outcome))} ${t.fg("dim", `${d.project ?? ""} › ${d.type ?? ""}`)}`,
|
|
104
|
+
},
|
|
105
|
+
...(d.similar ?? []).map((s) => t.fg("dim", `~ similar: ${s}`)),
|
|
103
106
|
];
|
|
104
|
-
for (const s of similar) lines.push(`~ similar: ${s}`);
|
|
105
|
-
return lines.join("\n");
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
/** Head `Memory "query" … N hits · P projects`, then one meter row per hit. */
|
|
110
|
+
export function searchRows(t: ThemeLike, query: string, hits: SearchHit[], shown = hits.length): RailRow[] {
|
|
109
111
|
const projects = new Set(hits.map((h) => h.wing)).size;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
return [
|
|
113
|
+
{ left: `${t.bold("Memory")} "${query}"`, right: t.fg("dim", `${plural(hits.length, "hit")} · ${plural(projects, "project")}`) },
|
|
114
|
+
...hits.slice(0, shown).map((h) => ({
|
|
115
|
+
left: `${meter(t, h.score, 8, MEMORY_COLOR)} ${h.title}`,
|
|
116
|
+
right: t.fg("dim", `${h.wing} › ${h.room} · ${sourceLabel(h.sourceLabel)}`),
|
|
117
|
+
})),
|
|
118
|
+
];
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
/** Search result card (also used by the global alias). */
|
|
122
|
+
function searchCard(t: ThemeLike, details: unknown, expanded: boolean): Component {
|
|
123
|
+
const d = details as { query?: string; hits?: SearchHit[] } | undefined;
|
|
124
|
+
const hits = d?.hits ?? [];
|
|
125
|
+
if (hits.length === 0) return memoryCard(t, [{ left: `${t.bold("Memory")} "${d?.query ?? ""}"`, right: t.fg("dim", "no matches") }]);
|
|
126
|
+
const shown = expanded ? hits.length : Math.min(5, hits.length);
|
|
127
|
+
const rows = searchRows(t, d?.query ?? "", hits, shown);
|
|
128
|
+
if (hits.length > shown) rows.push(t.fg("dim", `… ${String(hits.length - shown)} more`));
|
|
129
|
+
return memoryCard(t, rows);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** `Memory 12 stored` + one row per memory (title … type / project). */
|
|
133
|
+
function listCard(t: ThemeLike, details: unknown, expanded: boolean, global: boolean): Component {
|
|
134
|
+
const mems = (details as { memories?: Array<{ title: string; type: string; project?: string }> } | undefined)?.memories ?? [];
|
|
135
|
+
const shown = expanded ? mems : mems.slice(0, 8);
|
|
136
|
+
const rows: RailRow[] = [{ left: `${t.bold("Memory")} ${String(mems.length)} ${mems.length === 1 ? "memory" : "memories"}`, right: t.fg("dim", global ? "all projects" : "this project") }];
|
|
137
|
+
for (const m of shown) rows.push({ left: m.title, right: t.fg("dim", global ? `${m.project ?? ""} › ${m.type}` : m.type) });
|
|
138
|
+
if (mems.length > shown.length) rows.push(t.fg("dim", `… ${String(mems.length - shown.length)} more`));
|
|
139
|
+
return memoryCard(t, rows);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** The real tool bodies, callable outside the main registration — the
|
|
143
|
+
* background save session mounts these on its stub tools. */
|
|
144
|
+
export interface MemoryExecutors {
|
|
145
|
+
store: (
|
|
146
|
+
params: { title: string; content: string; tags?: string[]; type?: string },
|
|
147
|
+
ctx: { cwd: string },
|
|
148
|
+
) => Promise<{ content: { type: "text"; text: string }[]; details: Record<string, unknown> }>;
|
|
149
|
+
search: (params: {
|
|
150
|
+
query: string;
|
|
151
|
+
limit?: number;
|
|
152
|
+
scope?: string;
|
|
153
|
+
}) => Promise<{ content: { type: "text"; text: string }[]; details: Record<string, unknown> }>;
|
|
154
|
+
remove: (params: {
|
|
155
|
+
title?: string;
|
|
156
|
+
id?: string;
|
|
157
|
+
}) => Promise<{ content: { type: "text"; text: string }[]; details: Record<string, unknown> }>;
|
|
158
|
+
list: () => Promise<{ content: { type: "text"; text: string }[]; details: Record<string, unknown> }>;
|
|
159
|
+
globalList: () => Promise<{ content: { type: "text"; text: string }[]; details: Record<string, unknown> }>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
type EventSink = { events: { emit: (name: string, payload: unknown) => void } };
|
|
163
|
+
|
|
164
|
+
export function memoryExecutors(
|
|
165
|
+
pi: EventSink,
|
|
119
166
|
backend: () => SessionBackend | null,
|
|
120
167
|
activity?: ToolActivity,
|
|
121
|
-
|
|
122
|
-
): void {
|
|
168
|
+
): MemoryExecutors {
|
|
123
169
|
const W = () => backend();
|
|
124
|
-
// recallAtStart=off swaps the "call BEFORE work" nudge for neutral wording —
|
|
125
|
-
// the tools stay callable, the agent just isn't ordered to use them first.
|
|
126
|
-
const neutral = options?.neutral === true;
|
|
127
170
|
const localPeek = (title: string) => {
|
|
128
171
|
const b = W();
|
|
129
172
|
if (!b) return { exact: null as ReturnType<typeof findByTitle>, similar: [] as string[] };
|
|
@@ -135,7 +178,7 @@ export function registerMemoryTools(
|
|
|
135
178
|
return { exact, similar };
|
|
136
179
|
};
|
|
137
180
|
|
|
138
|
-
const
|
|
181
|
+
const store = async (
|
|
139
182
|
params: { title: string; content: string; tags?: string[]; type?: string },
|
|
140
183
|
ctx: { cwd: string },
|
|
141
184
|
) => {
|
|
@@ -195,6 +238,116 @@ export function registerMemoryTools(
|
|
|
195
238
|
};
|
|
196
239
|
};
|
|
197
240
|
|
|
241
|
+
const search = async (
|
|
242
|
+
params: { query: string; limit?: number; scope?: string },
|
|
243
|
+
) => {
|
|
244
|
+
activity?.onRecall?.();
|
|
245
|
+
const b = W();
|
|
246
|
+
if (!b) {
|
|
247
|
+
return {
|
|
248
|
+
content: [{ type: "text" as const, text: `Memory search unavailable — the memory backend isn't running.` }],
|
|
249
|
+
details: { results: [] },
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const limit = params.limit || 10;
|
|
253
|
+
const scope = params.scope === "project" ? "project" : "all";
|
|
254
|
+
const hits = await b.search(params.query, limit, scope);
|
|
255
|
+
if (hits.length === 0) {
|
|
256
|
+
return {
|
|
257
|
+
content: [{ type: "text" as const, text: `No memories found for: "${params.query}"` }],
|
|
258
|
+
details: { query: params.query, hits: [] },
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const output = hits
|
|
262
|
+
.map((h, i) => `${i + 1}. [${h.wing}] **${h.title}** (${h.room} · ${sourceLabel(h.sourceLabel)})\n ${h.snippet}`)
|
|
263
|
+
.join("\n\n");
|
|
264
|
+
return {
|
|
265
|
+
content: [{ type: "text" as const, text: `Found ${hits.length} memories:\n\n${output}` }],
|
|
266
|
+
details: { query: params.query, hits },
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const remove = async (params: { title?: string; id?: string }) => {
|
|
271
|
+
activity?.onStore?.();
|
|
272
|
+
const b = W();
|
|
273
|
+
if (!b) {
|
|
274
|
+
return { content: [{ type: "text" as const, text: `Memory backend unavailable — nothing deleted.` }], details: { deleted: false } };
|
|
275
|
+
}
|
|
276
|
+
const key = params.id || params.title;
|
|
277
|
+
if (!key) {
|
|
278
|
+
return { content: [{ type: "text" as const, text: "Provide a title or id to delete." }], details: { deleted: false } };
|
|
279
|
+
}
|
|
280
|
+
const res = await b.delete(b.project, key);
|
|
281
|
+
activity?.onWriteDone?.();
|
|
282
|
+
if (res.found) {
|
|
283
|
+
emitEvent(pi, UNIPI_EVENTS.MEMORY_DELETED, { id: key, title: key, project: b.project });
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
content: [{ type: "text" as const, text: res.found ? `Deleted memory: ${key} (${res.outcome})` : `Memory not found: ${key}` }],
|
|
287
|
+
details: { deleted: res.found, id: key, title: key, outcome: res.outcome },
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const list = async () => {
|
|
292
|
+
activity?.onRecall?.();
|
|
293
|
+
const b = W();
|
|
294
|
+
const memories = b ? await b.list() : [];
|
|
295
|
+
if (memories.length === 0) {
|
|
296
|
+
return { content: [{ type: "text" as const, text: "No memories stored for this project." }], details: { memories: [] } };
|
|
297
|
+
}
|
|
298
|
+
const output = memories.map((m) => `- ${m.title} (${m.type})`).join("\n");
|
|
299
|
+
return {
|
|
300
|
+
content: [{ type: "text" as const, text: `Project memories (${memories.length}):\n\n${output}` }],
|
|
301
|
+
details: { memories },
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const globalList = async () => {
|
|
306
|
+
activity?.onRecall?.();
|
|
307
|
+
const b = W();
|
|
308
|
+
if (!b) {
|
|
309
|
+
return { content: [{ type: "text" as const, text: "Memory backend unavailable." }], details: { memories: [] } };
|
|
310
|
+
}
|
|
311
|
+
// Pull every project dir's md files for a cross-project list.
|
|
312
|
+
const { listProjectDirs } = await import("./files.js");
|
|
313
|
+
const { sanitizeProjectName } = await import("./paths.js");
|
|
314
|
+
const memories: Array<{ project: string; id: string; title: string; type: string }> = [];
|
|
315
|
+
for (const { name } of listProjectDirs()) {
|
|
316
|
+
for (const m of await b.list(sanitizeProjectName(name))) {
|
|
317
|
+
memories.push(m);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (memories.length === 0) {
|
|
321
|
+
return { content: [{ type: "text" as const, text: "No memories stored in any project." }], details: { memories: [] } };
|
|
322
|
+
}
|
|
323
|
+
const grouped = new Map<string, typeof memories>();
|
|
324
|
+
for (const m of memories) {
|
|
325
|
+
grouped.set(m.project, [...(grouped.get(m.project) ?? []), m]);
|
|
326
|
+
}
|
|
327
|
+
let output = "";
|
|
328
|
+
for (const [p, ms] of grouped) {
|
|
329
|
+
output += `\n**${p}** (${ms.length}):\n` + ms.map((m) => ` - ${m.title} (${m.type})`).join("\n") + "\n";
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
content: [{ type: "text" as const, text: `All memories across ${grouped.size} projects (${memories.length} total):${output}` }],
|
|
333
|
+
details: { memories },
|
|
334
|
+
};
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
return { store, search, remove, list, globalList };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function registerMemoryTools(
|
|
341
|
+
pi: ExtensionAPI,
|
|
342
|
+
backend: () => SessionBackend | null,
|
|
343
|
+
activity?: ToolActivity,
|
|
344
|
+
options?: { neutral?: boolean },
|
|
345
|
+
): void {
|
|
346
|
+
// recallAtStart=off swaps the "call BEFORE work" nudge for neutral wording —
|
|
347
|
+
// the tools stay callable, the agent just isn't ordered to use them first.
|
|
348
|
+
const neutral = options?.neutral === true;
|
|
349
|
+
const ex = memoryExecutors(pi, backend, activity);
|
|
350
|
+
|
|
198
351
|
pi.registerTool({
|
|
199
352
|
name: MEMORY_TOOLS.STORE,
|
|
200
353
|
label: "Store Memory",
|
|
@@ -218,52 +371,19 @@ export function registerMemoryTools(
|
|
|
218
371
|
tags: Type.Optional(Type.Array(Type.String(), { description: "Tags for categorization" })),
|
|
219
372
|
type: Type.Optional(Type.String({ description: "Memory type", enum: [...MEMORY_TYPES] })),
|
|
220
373
|
}),
|
|
221
|
-
|
|
374
|
+
renderShell: "self",
|
|
375
|
+
renderCall: (args, theme, context) => pendingLine(theme, context, `remembering ${String(args.title ?? "").slice(0, 60)}…`),
|
|
222
376
|
renderResult: (result, _o, theme) => {
|
|
223
377
|
const d = result.details as { action?: string; outcome?: string; similar?: string[]; title?: string; project?: string; type?: string } | undefined;
|
|
224
378
|
const text = result.content?.map((c) => ("text" in c ? c.text : "")).join("\n") ?? "";
|
|
225
|
-
if (!d?.outcome) return
|
|
226
|
-
|
|
227
|
-
`${MEMORY_GLYPH} ${d.action === "updated" ? "updated" : "remembered"} ${d.title ?? ""}`,
|
|
228
|
-
`${d.project ?? ""} › ${d.type ?? ""} · ${outcomeLabel(d.outcome)}`,
|
|
229
|
-
...(d.similar ?? []).map((s) => `~ similar: ${s}`),
|
|
230
|
-
];
|
|
231
|
-
return frame(theme as ThemeLike, lines, outcomeTone(d.outcome));
|
|
379
|
+
if (!d?.outcome) return memoryCard(theme, [`${theme.bold("Memory")} ${theme.fg("warning", text.split("\n")[0] ?? "")}`], "warning");
|
|
380
|
+
return memoryCard(theme, storeRows(theme, d), outcomeTone(d.outcome));
|
|
232
381
|
},
|
|
233
382
|
async execute(_id, params, _s, _o, ctx) {
|
|
234
|
-
return
|
|
383
|
+
return ex.store(params, ctx);
|
|
235
384
|
},
|
|
236
385
|
});
|
|
237
386
|
|
|
238
|
-
const searchExecute = async (
|
|
239
|
-
params: { query: string; limit?: number; scope?: string },
|
|
240
|
-
) => {
|
|
241
|
-
activity?.onRecall?.();
|
|
242
|
-
const b = W();
|
|
243
|
-
if (!b) {
|
|
244
|
-
return {
|
|
245
|
-
content: [{ type: "text" as const, text: `Memory search unavailable — the memory backend isn't running.` }],
|
|
246
|
-
details: { results: [] },
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
const limit = params.limit || 10;
|
|
250
|
-
const scope = params.scope === "project" ? "project" : "all";
|
|
251
|
-
const hits = await b.search(params.query, limit, scope);
|
|
252
|
-
if (hits.length === 0) {
|
|
253
|
-
return {
|
|
254
|
-
content: [{ type: "text" as const, text: `No memories found for: "${params.query}"` }],
|
|
255
|
-
details: { results: [] },
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
const output = hits
|
|
259
|
-
.map((h, i) => `${i + 1}. [${h.wing}] **${h.title}** (${h.room} · ${sourceLabel(h.sourceLabel)})\n ${h.snippet}`)
|
|
260
|
-
.join("\n\n");
|
|
261
|
-
return {
|
|
262
|
-
content: [{ type: "text" as const, text: `Found ${hits.length} memories:\n\n${output}` }],
|
|
263
|
-
details: { query: params.query, hits },
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
|
|
267
387
|
pi.registerTool({
|
|
268
388
|
name: MEMORY_TOOLS.SEARCH,
|
|
269
389
|
label: "Search Memory",
|
|
@@ -291,17 +411,19 @@ export function registerMemoryTools(
|
|
|
291
411
|
limit: Type.Optional(Type.Number({ description: "Max results (default 10)", default: 10 })),
|
|
292
412
|
scope: Type.Optional(Type.String({ description: "'all' (default) or 'project'", enum: ["all", "project"], default: "all" })),
|
|
293
413
|
}),
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
414
|
+
renderShell: "self",
|
|
415
|
+
renderCall: (args, theme, context) => pendingLine(theme, context, `searching "${String(args.query).slice(0, 60)}"…`),
|
|
416
|
+
renderResult: (result, options, theme) => searchCard(theme, result.details, options.expanded),
|
|
417
|
+
// Retrieval is the deliberate exception to compact tool results: simple
|
|
418
|
+
// mode keeps the full search rail (every hit with its meter and source)
|
|
419
|
+
// under the collapsed row — a bare "N output lines" would hide exactly
|
|
420
|
+
// what the search was for.
|
|
421
|
+
...( {
|
|
422
|
+
simpleMeta: () => "",
|
|
423
|
+
simpleResult: (result: { details?: unknown }, theme: ThemeLike) => searchCard(theme, result.details, true),
|
|
424
|
+
} as object),
|
|
303
425
|
async execute(_id, params, _s, _o, _ctx) {
|
|
304
|
-
return
|
|
426
|
+
return ex.search(params);
|
|
305
427
|
},
|
|
306
428
|
});
|
|
307
429
|
|
|
@@ -314,18 +436,16 @@ export function registerMemoryTools(
|
|
|
314
436
|
query: Type.String({ description: "Search query" }),
|
|
315
437
|
limit: Type.Optional(Type.Number({ default: 10 })),
|
|
316
438
|
}),
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
},
|
|
439
|
+
renderShell: "self",
|
|
440
|
+
renderCall: (args, theme, context) => pendingLine(theme, context, `searching "${String(args.query).slice(0, 60)}"…`),
|
|
441
|
+
renderResult: (result, options, theme) => searchCard(theme, result.details, options.expanded),
|
|
442
|
+
// Same retrieval exception as memory_search.
|
|
443
|
+
...( {
|
|
444
|
+
simpleMeta: () => "",
|
|
445
|
+
simpleResult: (result: { details?: unknown }, theme: ThemeLike) => searchCard(theme, result.details, true),
|
|
446
|
+
} as object),
|
|
326
447
|
async execute(_id, params, _s, _o, _ctx) {
|
|
327
|
-
|
|
328
|
-
return searchExecute({ query: params.query, limit: params.limit, scope: "all" });
|
|
448
|
+
return ex.search({ query: params.query, limit: params.limit, scope: "all" });
|
|
329
449
|
},
|
|
330
450
|
});
|
|
331
451
|
|
|
@@ -338,34 +458,16 @@ export function registerMemoryTools(
|
|
|
338
458
|
title: Type.Optional(Type.String({ description: "Memory title to delete" })),
|
|
339
459
|
id: Type.Optional(Type.String({ description: "Memory ID to delete" })),
|
|
340
460
|
}),
|
|
341
|
-
|
|
461
|
+
renderShell: "self",
|
|
462
|
+
renderCall: (_args, theme, context) => pendingLine(theme, context, "forgetting…"),
|
|
342
463
|
renderResult: (result, _o, theme) => {
|
|
343
464
|
const d = result.details as Record<string, unknown> | undefined;
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
];
|
|
348
|
-
return frame(theme as ThemeLike, lines, d?.deleted ? outcomeTone(d.outcome ?? "filed") : "warning");
|
|
465
|
+
const outcome = String(d?.outcome ?? "filed");
|
|
466
|
+
const right = d?.deleted ? theme.fg(outcomeColor(outcome), outcomeLabel(outcome)) : theme.fg("warning", "not found");
|
|
467
|
+
return memoryCard(theme, [{ left: `${theme.bold("Memory")} ${theme.fg("dim", "forgot")} ${String(d?.title ?? d?.id ?? "memory")}`, right }], d?.deleted ? outcomeTone(outcome) : "warning");
|
|
349
468
|
},
|
|
350
469
|
async execute(_id, params, _s, _o, _ctx) {
|
|
351
|
-
|
|
352
|
-
const b = W();
|
|
353
|
-
if (!b) {
|
|
354
|
-
return { content: [{ type: "text" as const, text: "Memory backend unavailable — nothing deleted." }], details: { deleted: false } };
|
|
355
|
-
}
|
|
356
|
-
const key = params.id || params.title;
|
|
357
|
-
if (!key) {
|
|
358
|
-
return { content: [{ type: "text" as const, text: "Provide a title or id to delete." }], details: { deleted: false } };
|
|
359
|
-
}
|
|
360
|
-
const res = await b.delete(b.project, key);
|
|
361
|
-
activity?.onWriteDone?.();
|
|
362
|
-
if (res.found) {
|
|
363
|
-
emitEvent(pi, UNIPI_EVENTS.MEMORY_DELETED, { id: key, title: key, project: b.project });
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
content: [{ type: "text" as const, text: res.found ? `Deleted memory: ${key} (${res.outcome})` : `Memory not found: ${key}` }],
|
|
367
|
-
details: { deleted: res.found, id: key, title: key, outcome: res.outcome },
|
|
368
|
-
};
|
|
470
|
+
return ex.remove(params);
|
|
369
471
|
},
|
|
370
472
|
});
|
|
371
473
|
|
|
@@ -375,28 +477,11 @@ export function registerMemoryTools(
|
|
|
375
477
|
description: "List all memories for the current project.",
|
|
376
478
|
promptSnippet: "List all project memories.",
|
|
377
479
|
parameters: Type.Object({}),
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const mems = d?.memories ?? [];
|
|
382
|
-
const shown = options.expanded ? mems : mems.slice(0, 8);
|
|
383
|
-
const lines = [`${MEMORY_GLYPH} memories · ${mems.length} stored`];
|
|
384
|
-
for (const m of shown) lines.push(`${m.title} · ${m.type}`);
|
|
385
|
-
if (!options.expanded && mems.length > shown.length) lines.push(`… ${mems.length - shown.length} more`);
|
|
386
|
-
return frame(theme as ThemeLike, lines);
|
|
387
|
-
},
|
|
480
|
+
renderShell: "self",
|
|
481
|
+
renderCall: (_args, theme, context) => pendingLine(theme, context, "listing…"),
|
|
482
|
+
renderResult: (result, options, theme) => listCard(theme, result.details, options.expanded, false),
|
|
388
483
|
async execute(_id, _p, _s, _o, _ctx) {
|
|
389
|
-
|
|
390
|
-
const b = W();
|
|
391
|
-
const memories = b ? await b.list() : [];
|
|
392
|
-
if (memories.length === 0) {
|
|
393
|
-
return { content: [{ type: "text" as const, text: "No memories stored for this project." }], details: { memories: [] } };
|
|
394
|
-
}
|
|
395
|
-
const output = memories.map((m) => `- ${m.title} (${m.type})`).join("\n");
|
|
396
|
-
return {
|
|
397
|
-
content: [{ type: "text" as const, text: `Project memories (${memories.length}):\n\n${output}` }],
|
|
398
|
-
details: { memories },
|
|
399
|
-
};
|
|
484
|
+
return ex.list();
|
|
400
485
|
},
|
|
401
486
|
});
|
|
402
487
|
|
|
@@ -405,46 +490,11 @@ export function registerMemoryTools(
|
|
|
405
490
|
label: "List All Project Memories",
|
|
406
491
|
description: "List all memories across all projects with project names.",
|
|
407
492
|
parameters: Type.Object({}),
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const mems = d?.memories ?? [];
|
|
412
|
-
const shown = options.expanded ? mems : mems.slice(0, 8);
|
|
413
|
-
const lines = [`${MEMORY_GLYPH} memories · ${mems.length} stored across projects`];
|
|
414
|
-
for (const m of shown) lines.push(`[${m.project}] ${m.title} · ${m.type}`);
|
|
415
|
-
if (!options.expanded && mems.length > shown.length) lines.push(`… ${mems.length - shown.length} more`);
|
|
416
|
-
return frame(theme as ThemeLike, lines);
|
|
417
|
-
},
|
|
493
|
+
renderShell: "self",
|
|
494
|
+
renderCall: (_args, theme, context) => pendingLine(theme, context, "listing…"),
|
|
495
|
+
renderResult: (result, options, theme) => listCard(theme, result.details, options.expanded, true),
|
|
418
496
|
async execute(_id, _p, _s, _o, _ctx) {
|
|
419
|
-
|
|
420
|
-
const b = W();
|
|
421
|
-
if (!b) {
|
|
422
|
-
return { content: [{ type: "text" as const, text: "Memory backend unavailable." }], details: { memories: [] } };
|
|
423
|
-
}
|
|
424
|
-
// Pull every project dir's md files for a cross-project list.
|
|
425
|
-
const { listProjectDirs } = await import("./files.js");
|
|
426
|
-
const { sanitizeProjectName } = await import("./paths.js");
|
|
427
|
-
const memories: Array<{ project: string; id: string; title: string; type: string }> = [];
|
|
428
|
-
for (const { name } of listProjectDirs()) {
|
|
429
|
-
for (const m of await b.list(sanitizeProjectName(name))) {
|
|
430
|
-
memories.push(m);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
if (memories.length === 0) {
|
|
434
|
-
return { content: [{ type: "text" as const, text: "No memories stored in any project." }], details: { memories: [] } };
|
|
435
|
-
}
|
|
436
|
-
const grouped = new Map<string, typeof memories>();
|
|
437
|
-
for (const m of memories) {
|
|
438
|
-
grouped.set(m.project, [...(grouped.get(m.project) ?? []), m]);
|
|
439
|
-
}
|
|
440
|
-
let output = "";
|
|
441
|
-
for (const [p, ms] of grouped) {
|
|
442
|
-
output += `\n**${p}** (${ms.length}):\n` + ms.map((m) => ` - ${m.title} (${m.type})`).join("\n") + "\n";
|
|
443
|
-
}
|
|
444
|
-
return {
|
|
445
|
-
content: [{ type: "text" as const, text: `All memories across ${grouped.size} projects (${memories.length} total):${output}` }],
|
|
446
|
-
details: { memories },
|
|
447
|
-
};
|
|
497
|
+
return ex.globalList();
|
|
448
498
|
},
|
|
449
499
|
});
|
|
450
500
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/notify",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.21",
|
|
4
4
|
"description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.21",
|
|
38
38
|
"node-notifier": "^10.0.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|