@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
|
@@ -7,19 +7,23 @@
|
|
|
7
7
|
* ARCHITECTURE:
|
|
8
8
|
* - The overlay ONLY captures action selection (pure UI, no side effects)
|
|
9
9
|
* - All actions execute OUTSIDE the overlay via callbacks after done()
|
|
10
|
-
* - Undo
|
|
11
|
-
*
|
|
10
|
+
* - Undo history: a BurstTracker watches onTerminalInput and records the
|
|
11
|
+
* editor text twice per typing burst (open + close) — O(1) per keystroke.
|
|
12
|
+
* - Y copies the LAST ASSISTANT RESPONSE via pi's copyToClipboard;
|
|
13
|
+
* K adds the editor text to the kanboard backlog (no title).
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
-
import {
|
|
17
|
+
import { copyToClipboard } from "@earendil-works/pi-coding-agent";
|
|
18
|
+
import { Key } from "@earendil-works/pi-tui";
|
|
16
19
|
import { MODULES, emitEvent, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
17
20
|
import { RegisterStore } from "./registers.ts";
|
|
18
|
-
import {
|
|
21
|
+
import { EditHistory } from "./undo-redo.ts";
|
|
22
|
+
import { BurstTracker } from "./burst.ts";
|
|
23
|
+
import { getLastResponseText, type SessionEntryLike } from "./last-response.ts";
|
|
19
24
|
import { ChordOverlay, type ChordCallbacks } from "./chord-overlay.ts";
|
|
20
25
|
import { loadConfig } from "./settings.ts";
|
|
21
|
-
import {
|
|
22
|
-
import { THINKING_CYCLE } from "./types.ts";
|
|
26
|
+
import { installClearedInput } from "./cleared-input.ts";
|
|
23
27
|
|
|
24
28
|
// ─── Status feedback ────────────────────────────────────────────────────────
|
|
25
29
|
|
|
@@ -46,107 +50,29 @@ function showError(ctx: ExtensionContext, text: string): void {
|
|
|
46
50
|
export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
47
51
|
// Shared state
|
|
48
52
|
const registers = new RegisterStore();
|
|
49
|
-
const
|
|
53
|
+
const history = new EditHistory();
|
|
54
|
+
const burst = new BurstTracker({
|
|
55
|
+
getText: () => ui?.getEditorText() ?? "",
|
|
56
|
+
record: (text) => history.record(text),
|
|
57
|
+
now: Date.now,
|
|
58
|
+
setTimeout: (handler, ms) => setTimeout(handler, ms),
|
|
59
|
+
clearTimeout: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),
|
|
60
|
+
});
|
|
50
61
|
|
|
51
|
-
// Persistent UI reference (captured
|
|
62
|
+
// Persistent UI reference (captured when the tracker installs, persists for session)
|
|
52
63
|
let ui: ExtensionContext["ui"] | null = null;
|
|
53
|
-
let
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// - On each keypress, capture text BEFORE the editor processes it
|
|
66
|
-
// - `pendingSnapshot` = text before the current typing session started (first keypress)
|
|
67
|
-
// - `keystrokeCount` = how many edit keys pressed since last snapshot
|
|
68
|
-
// - `lastSnapshotAt` = timestamp of last snapshot commit
|
|
69
|
-
// - 500ms timer resets on each keypress (fires only on pause)
|
|
70
|
-
//
|
|
71
|
-
// Example: user types "hello world" continuously:
|
|
72
|
-
// - Key 1: pendingSnapshot = "", count=1
|
|
73
|
-
// - Key 10: count=10 (no trigger yet)
|
|
74
|
-
// - Key 20: count=20 → COMMIT snapshot="", reset. Now pendingSnapshot=current
|
|
75
|
-
// - User pauses 500ms → COMMIT snapshot=current, reset
|
|
76
|
-
//
|
|
77
|
-
// Example: user types slowly (1 char per second):
|
|
78
|
-
// - Key 1: pendingSnapshot="", count=1, timer starts
|
|
79
|
-
// - Key 2 (1s later): timer was reset, count=2
|
|
80
|
-
// - ... (timer fires after each pause between keys)
|
|
81
|
-
// - Each pause triggers a snapshot
|
|
82
|
-
|
|
83
|
-
let pendingSnapshot: string | null = null;
|
|
84
|
-
let keystrokeCount = 0;
|
|
85
|
-
let lastSnapshotAt = 0;
|
|
86
|
-
let snapshotTimer: ReturnType<typeof setTimeout> | null = null;
|
|
87
|
-
|
|
88
|
-
const SNAPSHOT_PAUSE_MS = 500; // pause trigger
|
|
89
|
-
const SNAPSHOT_COUNT_THRESHOLD = 20; // character count trigger
|
|
90
|
-
const SNAPSHOT_TIME_MS = 3000; // time trigger
|
|
91
|
-
|
|
92
|
-
/** Commit the pending snapshot and reset all tracking state. */
|
|
93
|
-
function commitSnapshot(): void {
|
|
94
|
-
if (pendingSnapshot !== null) {
|
|
95
|
-
undoRedo.snapshot(pendingSnapshot);
|
|
96
|
-
}
|
|
97
|
-
pendingSnapshot = null;
|
|
98
|
-
keystrokeCount = 0;
|
|
99
|
-
lastSnapshotAt = Date.now();
|
|
100
|
-
if (snapshotTimer) {
|
|
101
|
-
clearTimeout(snapshotTimer);
|
|
102
|
-
snapshotTimer = null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function setupInputListener(): void {
|
|
107
|
-
if (inputListenerRegistered || !ui) return;
|
|
108
|
-
inputListenerRegistered = true;
|
|
109
|
-
|
|
110
|
-
ui.onTerminalInput((data: string) => {
|
|
111
|
-
if (!ui || suppressInputListener) return;
|
|
112
|
-
|
|
113
|
-
// Only snapshot for edit keys (printable, backspace, delete, enter)
|
|
114
|
-
const isEditKey = data.length === 1 || data === "\x7f" || matchesKey(data, Key.delete) || data === "\r" || data === "\n";
|
|
115
|
-
if (!isEditKey) return;
|
|
116
|
-
|
|
117
|
-
// Capture text BEFORE the keypress is processed by the editor
|
|
118
|
-
const textBefore = ui.getEditorText();
|
|
119
|
-
|
|
120
|
-
// On first keypress of a new session, store the pending snapshot
|
|
121
|
-
if (pendingSnapshot === null) {
|
|
122
|
-
pendingSnapshot = textBefore;
|
|
123
|
-
lastSnapshotAt = Date.now();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
keystrokeCount++;
|
|
127
|
-
|
|
128
|
-
// ─── Trigger 1: Character count threshold (20 chars) ─────────
|
|
129
|
-
if (keystrokeCount >= SNAPSHOT_COUNT_THRESHOLD) {
|
|
130
|
-
commitSnapshot();
|
|
131
|
-
// Don't return — let the pause timer restart below
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// ─── Trigger 2: Time threshold (3 seconds) ───────────────────
|
|
135
|
-
if (pendingSnapshot !== null && Date.now() - lastSnapshotAt >= SNAPSHOT_TIME_MS) {
|
|
136
|
-
commitSnapshot();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ─── Trigger 3: Pause timer (500ms after last keypress) ──────
|
|
140
|
-
// Reset the pause timer on each keypress
|
|
141
|
-
if (snapshotTimer) {
|
|
142
|
-
clearTimeout(snapshotTimer);
|
|
143
|
-
}
|
|
144
|
-
snapshotTimer = setTimeout(() => {
|
|
145
|
-
// User stopped typing — commit the snapshot
|
|
146
|
-
if (pendingSnapshot !== null) {
|
|
147
|
-
commitSnapshot();
|
|
148
|
-
}
|
|
149
|
-
}, SNAPSHOT_PAUSE_MS);
|
|
64
|
+
let uninstallInput: (() => void) | null = null;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Install the burst tracker on the editor input stream — idempotent.
|
|
68
|
+
* Called from session_start (so history exists before the first chord)
|
|
69
|
+
* and lazily from the chord handler as a fallback.
|
|
70
|
+
*/
|
|
71
|
+
function installBurstTracker(ctx: ExtensionContext): void {
|
|
72
|
+
if (uninstallInput || !ctx.hasUI) return;
|
|
73
|
+
ui = ctx.ui;
|
|
74
|
+
uninstallInput = ctx.ui.onTerminalInput(() => {
|
|
75
|
+
burst.onInput();
|
|
150
76
|
});
|
|
151
77
|
}
|
|
152
78
|
|
|
@@ -156,9 +82,10 @@ export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
|
156
82
|
function doStash(ctx: ExtensionContext): void {
|
|
157
83
|
const text = ctx.ui.getEditorText();
|
|
158
84
|
if (text.length > 0) {
|
|
159
|
-
|
|
85
|
+
history.record(text); // state before clearing
|
|
160
86
|
registers.setStash(text);
|
|
161
87
|
ctx.ui.setEditorText("");
|
|
88
|
+
history.record("");
|
|
162
89
|
showSuccess(ctx, "✓ stash saved");
|
|
163
90
|
} else {
|
|
164
91
|
const stash = registers.getStash();
|
|
@@ -166,48 +93,35 @@ export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
|
166
93
|
showError(ctx, "stash empty");
|
|
167
94
|
return;
|
|
168
95
|
}
|
|
169
|
-
|
|
96
|
+
history.record("");
|
|
170
97
|
ctx.ui.setEditorText(stash);
|
|
98
|
+
history.record(stash);
|
|
171
99
|
showSuccess(ctx, "✓ stash restored");
|
|
172
100
|
}
|
|
173
101
|
}
|
|
174
102
|
|
|
175
103
|
function doUndo(ctx: ExtensionContext): void {
|
|
176
|
-
|
|
104
|
+
burst.close(); // capture un-flushed typing before stepping
|
|
177
105
|
const current = ctx.ui.getEditorText();
|
|
178
|
-
const result =
|
|
106
|
+
const result = history.undo(current);
|
|
179
107
|
if (result.ok) {
|
|
180
108
|
ctx.ui.setEditorText(result.text);
|
|
181
109
|
showSuccess(ctx, "✓ undo");
|
|
182
110
|
} else {
|
|
183
111
|
showError(ctx, "nothing to undo");
|
|
184
112
|
}
|
|
185
|
-
suppressInputListener = false;
|
|
186
113
|
}
|
|
187
114
|
|
|
188
115
|
function doRedo(ctx: ExtensionContext): void {
|
|
189
|
-
|
|
116
|
+
burst.close();
|
|
190
117
|
const current = ctx.ui.getEditorText();
|
|
191
|
-
const result =
|
|
118
|
+
const result = history.redo(current);
|
|
192
119
|
if (result.ok) {
|
|
193
120
|
ctx.ui.setEditorText(result.text);
|
|
194
121
|
showSuccess(ctx, "✓ redo");
|
|
195
122
|
} else {
|
|
196
123
|
showError(ctx, "nothing to redo");
|
|
197
124
|
}
|
|
198
|
-
suppressInputListener = false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function doAppendRegister(ctx: ExtensionContext, index: number): void {
|
|
202
|
-
const regText = registers.getRegister(index);
|
|
203
|
-
if (regText.length === 0) {
|
|
204
|
-
showError(ctx, `register ${index} empty`);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
const current = ctx.ui.getEditorText();
|
|
208
|
-
undoRedo.snapshot(current);
|
|
209
|
-
ctx.ui.setEditorText(current + regText);
|
|
210
|
-
showSuccess(ctx, `✓ register ${index} appended`);
|
|
211
125
|
}
|
|
212
126
|
|
|
213
127
|
function doAppendStash(ctx: ExtensionContext): void {
|
|
@@ -216,92 +130,84 @@ export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
|
216
130
|
showError(ctx, "stash empty");
|
|
217
131
|
return;
|
|
218
132
|
}
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
133
|
+
const before = ctx.ui.getEditorText();
|
|
134
|
+
history.record(before);
|
|
135
|
+
const after = before + stashText;
|
|
136
|
+
ctx.ui.setEditorText(after);
|
|
137
|
+
history.record(after);
|
|
222
138
|
showSuccess(ctx, "✓ stash appended");
|
|
223
139
|
}
|
|
224
140
|
|
|
225
|
-
function
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
141
|
+
async function doCopyLastResponse(ctx: ExtensionContext): Promise<void> {
|
|
142
|
+
const entries = ctx.sessionManager.getBranch() as unknown as SessionEntryLike[];
|
|
143
|
+
const text = getLastResponseText(entries);
|
|
144
|
+
if (!text) {
|
|
145
|
+
showError(ctx, "no response to copy");
|
|
229
146
|
return;
|
|
230
147
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
showSuccess(ctx, "✓ copied");
|
|
234
|
-
}
|
|
235
|
-
showError(ctx,
|
|
148
|
+
try {
|
|
149
|
+
await copyToClipboard(text);
|
|
150
|
+
showSuccess(ctx, "✓ copied last response");
|
|
151
|
+
} catch (error) {
|
|
152
|
+
showError(ctx, `copy failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
153
|
}
|
|
237
154
|
}
|
|
238
155
|
|
|
239
|
-
function
|
|
156
|
+
async function doKanboard(ctx: ExtensionContext): Promise<void> {
|
|
240
157
|
const text = ctx.ui.getEditorText();
|
|
241
|
-
if (text.length === 0) {
|
|
242
|
-
showError(ctx, "nothing to
|
|
158
|
+
if (text.trim().length === 0) {
|
|
159
|
+
showError(ctx, "nothing to add");
|
|
243
160
|
return;
|
|
244
161
|
}
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
|
|
162
|
+
const api = globalThis.__unipi_kanboard_api;
|
|
163
|
+
if (!api) {
|
|
164
|
+
showError(ctx, "kanboard not loaded");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let result: Awaited<ReturnType<typeof api.captureToBacklog>>;
|
|
168
|
+
try {
|
|
169
|
+
result = await api.captureToBacklog({ cwd: ctx.cwd, text });
|
|
170
|
+
} catch (error) {
|
|
171
|
+
showError(ctx, `kanboard: ${error instanceof Error ? error.message : String(error)}`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (!result.ok) {
|
|
175
|
+
showError(ctx, result.reason);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// The capture takes ~100ms; only clear the editor if the user has not
|
|
179
|
+
// typed since — otherwise the new text stays and just gets the status.
|
|
180
|
+
if (ctx.ui.getEditorText() === text) {
|
|
181
|
+
history.record(text); // state before clearing
|
|
248
182
|
ctx.ui.setEditorText("");
|
|
249
|
-
|
|
250
|
-
} else {
|
|
251
|
-
showError(ctx, result.reason ?? "clipboard unavailable");
|
|
183
|
+
history.record("");
|
|
252
184
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
function doToggleThinking(): void {
|
|
256
|
-
const current = pi.getThinkingLevel();
|
|
257
|
-
const idx = THINKING_CYCLE.indexOf(current as any);
|
|
258
|
-
const nextIdx = idx >= 0 ? (idx + 1) % THINKING_CYCLE.length : 0;
|
|
259
|
-
const next = THINKING_CYCLE[nextIdx];
|
|
260
|
-
pi.setThinkingLevel(next as any);
|
|
261
|
-
// Note: no ctx available here for status, but thinking level is visible in UI
|
|
185
|
+
const att = `(${result.attachments} attachment${result.attachments === 1 ? "" : "s"})`;
|
|
186
|
+
showSuccess(ctx, `✓ ${result.id} added to Backlog ${att}`);
|
|
262
187
|
}
|
|
263
188
|
|
|
264
189
|
// ─── Register ALT+S shortcut — opens chord overlay ─────────────────────
|
|
265
190
|
|
|
266
191
|
pi.registerShortcut(Key.alt("s"), {
|
|
267
|
-
description: "Input shortcuts — stash, undo, redo,
|
|
192
|
+
description: "Input shortcuts — stash, undo, redo, append stash, copy last response, kanboard",
|
|
268
193
|
handler: async (ctx: ExtensionContext) => {
|
|
269
194
|
if (!ctx.hasUI) return;
|
|
270
195
|
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
ui = ctx.ui;
|
|
274
|
-
setupInputListener();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Suppress input listener while overlay is open.
|
|
278
|
-
// The onTerminalInput handler fires for the ALT+S keypress itself,
|
|
279
|
-
// capturing the current text as a pending snapshot. If we don't suppress,
|
|
280
|
-
// that snapshot would be committed after undo runs, creating a "undo undoes undo" loop.
|
|
281
|
-
suppressInputListener = true;
|
|
282
|
-
if (snapshotTimer) { clearTimeout(snapshotTimer); snapshotTimer = null; }
|
|
283
|
-
pendingSnapshot = null;
|
|
284
|
-
keystrokeCount = 0;
|
|
196
|
+
// Fallback install (session_start normally did this already).
|
|
197
|
+
installBurstTracker(ctx);
|
|
285
198
|
|
|
286
199
|
void ctx.ui.custom<void>(
|
|
287
200
|
async (tui, theme, keybindings, done) => {
|
|
288
|
-
const wrappedDone = () => {
|
|
289
|
-
suppressInputListener = false;
|
|
290
|
-
done();
|
|
291
|
-
};
|
|
292
|
-
|
|
293
201
|
const callbacks: ChordCallbacks = {
|
|
294
202
|
onStash: () => doStash(ctx),
|
|
295
203
|
onUndo: () => doUndo(ctx),
|
|
296
204
|
onRedo: () => doRedo(ctx),
|
|
297
|
-
onAppendRegister: (index) => doAppendRegister(ctx, index),
|
|
298
205
|
onAppendStash: () => doAppendStash(ctx),
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
onToggleThinking: () => doToggleThinking(),
|
|
206
|
+
onCopyLastResponse: () => doCopyLastResponse(ctx),
|
|
207
|
+
onKanboard: () => doKanboard(ctx),
|
|
302
208
|
};
|
|
303
209
|
|
|
304
|
-
return new ChordOverlay(tui, theme, keybindings,
|
|
210
|
+
return new ChordOverlay(tui, theme, keybindings, done, callbacks);
|
|
305
211
|
},
|
|
306
212
|
{
|
|
307
213
|
overlay: true,
|
|
@@ -326,17 +232,23 @@ export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
|
326
232
|
},
|
|
327
233
|
});
|
|
328
234
|
|
|
235
|
+
// ─── Ctrl+C keeps the cleared text (struck through, ↑ restores) ────────
|
|
236
|
+
installClearedInput(pi);
|
|
237
|
+
|
|
329
238
|
// ─── Session lifecycle ─────────────────────────────────────────────────
|
|
330
239
|
|
|
240
|
+
pi.on("session_start", async (_event, ctx: ExtensionContext) => {
|
|
241
|
+
installBurstTracker(ctx);
|
|
242
|
+
});
|
|
243
|
+
|
|
331
244
|
pi.on("session_shutdown", async () => {
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
|
|
245
|
+
if (uninstallInput) {
|
|
246
|
+
uninstallInput();
|
|
247
|
+
uninstallInput = null;
|
|
335
248
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
undoRedo.clear();
|
|
249
|
+
burst.cancel();
|
|
250
|
+
ui = null;
|
|
251
|
+
history.clear();
|
|
340
252
|
});
|
|
341
253
|
|
|
342
254
|
// ─── Info-screen registration ────────────────────────────────────────────
|
|
@@ -353,20 +265,14 @@ export default function inputShortcutsExtension(pi: ExtensionAPI): void {
|
|
|
353
265
|
stats: [
|
|
354
266
|
{ id: "chordKey", label: "Chord key", show: true },
|
|
355
267
|
{ id: "tabInsertKey", label: "Tab insert key", show: true },
|
|
356
|
-
{ id: "registersUsed", label: "Registers used", show: true },
|
|
357
268
|
{ id: "stashStatus", label: "Stash", show: true },
|
|
358
269
|
],
|
|
359
270
|
},
|
|
360
271
|
dataProvider: async () => {
|
|
361
272
|
const config = loadConfig();
|
|
362
|
-
let used = 0;
|
|
363
|
-
for (let i = 0; i <= 9; i++) {
|
|
364
|
-
if (registers.getRegister(i).length > 0) used++;
|
|
365
|
-
}
|
|
366
273
|
return {
|
|
367
274
|
chordKey: { value: config.chordKey, detail: "Key to open shortcuts overlay" },
|
|
368
275
|
tabInsertKey: { value: config.tabInsertKey, detail: "Key to insert tab" },
|
|
369
|
-
registersUsed: { value: `${used}/10`, detail: "Non-empty numbered registers" },
|
|
370
276
|
stashStatus: { value: registers.getStash().length > 0 ? "set" : "empty", detail: "Stash register" },
|
|
371
277
|
};
|
|
372
278
|
},
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The text of the LAST assistant response — what pi's own `/copy` copies
|
|
3
|
+
* (see `getLastAssistantText` in pi's agent-session), mirrored through the
|
|
4
|
+
* extension API: `ctx.sessionManager.getBranch()` entries, newest last.
|
|
5
|
+
*
|
|
6
|
+
* Thinking blocks and tool calls are skipped, aborted messages with no
|
|
7
|
+
* content are skipped, and an assistant message whose text is empty does not
|
|
8
|
+
* stop the search — the latest response WITH text wins.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Structural subset of a session entry (pi SessionEntry) — testable. */
|
|
12
|
+
export interface SessionEntryLike {
|
|
13
|
+
type?: string;
|
|
14
|
+
message?: {
|
|
15
|
+
role?: string;
|
|
16
|
+
stopReason?: string;
|
|
17
|
+
content?: Array<{ type: string; text?: string }>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getLastResponseText(entries: readonly SessionEntryLike[] | undefined): string | undefined {
|
|
22
|
+
if (!entries) return undefined;
|
|
23
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
24
|
+
const entry = entries[i];
|
|
25
|
+
if (!entry || entry.type !== "message") continue;
|
|
26
|
+
const message = entry.message;
|
|
27
|
+
if (!message || message.role !== "assistant") continue;
|
|
28
|
+
// Mirror pi: an aborted message with no content is not a response.
|
|
29
|
+
if (message.stopReason === "aborted" && (message.content?.length ?? 0) === 0) continue;
|
|
30
|
+
let text = "";
|
|
31
|
+
for (const block of message.content ?? []) {
|
|
32
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
33
|
+
text += block.text;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
text = text.trim();
|
|
37
|
+
if (text) return text;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Stash store with JSON file persistence.
|
|
3
|
+
* The file lives at .unipi/config/input-shortcuts.json. Older versions stored
|
|
4
|
+
* ten numbered registers (0-9) next to the stash; those keys are ignored on
|
|
5
|
+
* load and dropped on the next save.
|
|
5
6
|
* Atomic writes (write to .tmp then rename).
|
|
6
7
|
*/
|
|
7
8
|
|
|
@@ -10,11 +11,6 @@ import { dirname, join } from "node:path";
|
|
|
10
11
|
import type { RegisterData } from "./types.ts";
|
|
11
12
|
import { REGISTERS_FILE } from "./types.ts";
|
|
12
13
|
|
|
13
|
-
const EMPTY_DATA: RegisterData = {
|
|
14
|
-
stash: "",
|
|
15
|
-
registers: ["", "", "", "", "", "", "", "", "", ""],
|
|
16
|
-
};
|
|
17
|
-
|
|
18
14
|
export class RegisterStore {
|
|
19
15
|
private data: RegisterData | null = null;
|
|
20
16
|
private filePath: string;
|
|
@@ -37,13 +33,6 @@ export class RegisterStore {
|
|
|
37
33
|
this.save();
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
/** Get a numbered register (0-9). */
|
|
41
|
-
getRegister(index: number): string {
|
|
42
|
-
if (index < 0 || index > 9) return "";
|
|
43
|
-
this.ensureLoaded();
|
|
44
|
-
return this.data!.registers[index] ?? "";
|
|
45
|
-
}
|
|
46
|
-
|
|
47
36
|
/** Lazy load from disk on first access. */
|
|
48
37
|
private ensureLoaded(): void {
|
|
49
38
|
if (this.loaded) return;
|
|
@@ -53,17 +42,13 @@ export class RegisterStore {
|
|
|
53
42
|
if (existsSync(this.filePath)) {
|
|
54
43
|
const raw = readFileSync(this.filePath, "utf-8");
|
|
55
44
|
const parsed = JSON.parse(raw) as Partial<RegisterData>;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
registers: Array.isArray(parsed.registers) && parsed.registers.length === 10
|
|
59
|
-
? parsed.registers.map((r) => (typeof r === "string" ? r : ""))
|
|
60
|
-
: [...EMPTY_DATA.registers],
|
|
61
|
-
};
|
|
45
|
+
// Extra keys (the old numbered registers) are ignored, not an error.
|
|
46
|
+
this.data = { stash: typeof parsed.stash === "string" ? parsed.stash : "" };
|
|
62
47
|
} else {
|
|
63
|
-
this.data = {
|
|
48
|
+
this.data = { stash: "" };
|
|
64
49
|
}
|
|
65
50
|
} catch {
|
|
66
|
-
this.data = {
|
|
51
|
+
this.data = { stash: "" };
|
|
67
52
|
}
|
|
68
53
|
}
|
|
69
54
|
|
|
@@ -2,14 +2,8 @@
|
|
|
2
2
|
* Shared type definitions for input-shortcuts package.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export interface TextSnapshot {
|
|
6
|
-
text: string;
|
|
7
|
-
timestamp: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
5
|
export interface RegisterData {
|
|
11
6
|
stash: string;
|
|
12
|
-
registers: string[];
|
|
13
7
|
}
|
|
14
8
|
|
|
15
9
|
export interface InputShortcutsConfig {
|
|
@@ -21,14 +15,13 @@ export type ChordAction =
|
|
|
21
15
|
| "stash"
|
|
22
16
|
| "redo"
|
|
23
17
|
| "undo"
|
|
24
|
-
| "appendRegister"
|
|
25
18
|
| "appendStash"
|
|
26
|
-
| "
|
|
27
|
-
| "
|
|
28
|
-
| "toggleThinking"
|
|
19
|
+
| "copyLastResponse"
|
|
20
|
+
| "kanboard"
|
|
29
21
|
| "tab";
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
/** The overlay shows only the root menu; Esc/unknown key closes silently. */
|
|
24
|
+
export type ChordState = "idle" | "chord_root";
|
|
32
25
|
|
|
33
26
|
export const DEFAULT_CONFIG: InputShortcutsConfig = {
|
|
34
27
|
chordKey: "alt+s",
|
|
@@ -37,12 +30,7 @@ export const DEFAULT_CONFIG: InputShortcutsConfig = {
|
|
|
37
30
|
|
|
38
31
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
39
32
|
|
|
40
|
-
export const UNDO_DEBOUNCE_MS = 500;
|
|
41
|
-
export const MAX_UNDO_SNAPSHOTS = 50;
|
|
42
33
|
export const STATUS_SUCCESS_MS = 2000;
|
|
43
34
|
export const STATUS_ERROR_MS = 3000;
|
|
44
35
|
export const REGISTERS_FILE = ".unipi/config/input-shortcuts.json";
|
|
45
36
|
export const CONFIG_FILE = ".unipi/config/input-shortcuts-config.json";
|
|
46
|
-
|
|
47
|
-
// Thinking level cycle for toggle action
|
|
48
|
-
export const THINKING_CYCLE = ["off", "low", "medium", "high", "xhigh"] as const;
|