@selesai/code 0.13.12 → 0.13.14
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 +9 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +77 -1
- package/dist/extensions/pi-subagents/VISION.md +12 -1
- package/dist/extensions/pi-subagents/docs/agents.md +13 -6
- package/dist/extensions/pi-subagents/docs/configuration.md +35 -9
- package/dist/extensions/pi-subagents/docs/extension-api.md +1 -1
- package/dist/extensions/pi-subagents/docs/missions.md +1 -1
- package/dist/extensions/pi-subagents/docs/models.md +6 -6
- package/dist/extensions/pi-subagents/docs/observability.md +6 -3
- package/dist/extensions/pi-subagents/docs/tool-reference.md +3 -3
- package/dist/extensions/pi-subagents/docs/watchdog.md +92 -114
- package/dist/extensions/pi-subagents/docs/workflows.md +1 -1
- package/dist/extensions/pi-subagents/install.mjs +1 -2
- package/dist/extensions/pi-subagents/package.json +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +6 -6
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +4 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +1 -1
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +3 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +120 -124
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +5 -1
- package/dist/extensions/pi-subagents/src/api/preflight.ts +4 -0
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +3 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +20 -0
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +1 -0
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +6 -2
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +1 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +19 -13
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +26 -8
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +103 -23
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +6 -2
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +54 -3
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +22 -2
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +63 -6
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +69 -12
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +13 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +21 -8
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +59 -6
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +95 -18
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +11 -43
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +24 -3
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +2 -6
- package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +1 -0
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +33 -18
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +73 -37
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +33 -6
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +4 -2
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +20 -3
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +21 -7
- package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +467 -63
- package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +3 -1
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +0 -12
- package/dist/extensions/pi-subagents/src/shared/fork-session-cwd.ts +27 -0
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +3 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +42 -4
- package/dist/extensions/pi-subagents/src/shared/utils.ts +18 -7
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +1 -1
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +26 -12
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +61 -2
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +12 -7
- package/dist/extensions/pi-subagents/src/tui/render.ts +227 -14
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +56 -34
- package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +77 -0
- package/dist/extensions/pi-subagents/src/watchdog/emission-guard.ts +5 -3
- package/dist/extensions/pi-subagents/src/watchdog/guidance.ts +20 -0
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +16 -13
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +10 -9
- package/dist/extensions/pi-subagents/src/watchdog/render.ts +4 -5
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +15 -4
- package/dist/extensions/pi-subagents/src/watchdog/rules.ts +70 -0
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +75 -92
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +2 -1
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +48 -104
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +18 -32
- package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +0 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -2
- package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +439 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +28 -1
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +335 -21
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +4 -1
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +22 -18
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +0 -1
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +21 -18
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +307 -22
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +25 -0
- package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +15 -4
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -2
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +96 -15
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +53 -5
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +221 -8
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +45 -24
- package/dist/extensions/pi-subagents/test/unit/agent-scan-dirs.test.ts +133 -0
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +4 -1
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +18 -4
- package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +16 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +38 -0
- package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +19 -6
- package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +22 -1
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +2 -6
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +66 -1
- package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +116 -10
- package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +136 -18
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +127 -48
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +68 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +17 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +9 -9
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +9 -3
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +22 -9
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +91 -8
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +0 -1
- package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +73 -13
- package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +79 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +2 -4
- package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -8
- package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +48 -3
- package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +37 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +36 -118
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +37 -14
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +45 -26
- package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +223 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +50 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +136 -4
- package/dist/extensions/pi-zentui/README.md +19 -5
- package/dist/extensions/pi-zentui/docs/configuration.md +37 -9
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +29 -0
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +31 -2
- package/dist/extensions/pi-zentui/extensions/zentui/prototype-patch-registry.ts +55 -11
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +115 -3
- package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +119 -2
- package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +1768 -0
- package/dist/extensions/pi-zentui/extensions/zentui/thinking-status.ts +69 -0
- package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +155 -0
- package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +2 -1
- package/dist/extensions/pi-zentui/extensions/zentui/user-message-osc.ts +16 -2
- package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +1 -1
- package/dist/extensions/pi-zentui/test/config-load-lifecycle.test.ts +124 -0
- package/dist/extensions/pi-zentui/test/config.test.ts +82 -2
- package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +19 -4
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +58 -9
- package/dist/extensions/pi-zentui/test/package-contents.mjs +33 -0
- package/dist/extensions/pi-zentui/test/prototype-patch-registry.test.ts +131 -0
- package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +4 -4
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +289 -7
- package/dist/extensions/pi-zentui/test/settings-previews.test.ts +106 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +51 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-loader-diagnostics.mjs +54 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-missing-export.test.ts +44 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +297 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +2329 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +1668 -0
- package/dist/extensions/pi-zentui/test/thinking-status.test.ts +85 -0
- package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +122 -0
- package/dist/extensions/pi-zentui/test/user-message-osc.test.ts +58 -0
- package/dist/skills/brandkit/SKILL.md +0 -2
- package/dist/skills/{industrial-brutalist-ui → brutalist}/SKILL.md +1 -3
- package/dist/skills/gpt-taste/SKILL.md +0 -2
- package/dist/skills/image-to-code/SKILL.md +0 -2
- package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -2
- package/dist/skills/imagegen-frontend-web/SKILL.md +0 -2
- package/dist/skills/{minimalist-ui → minimalist}/SKILL.md +1 -3
- package/dist/skills/{full-output-enforcement → output}/SKILL.md +1 -3
- package/dist/skills/{redesign-existing-projects → redesign}/SKILL.md +1 -3
- package/dist/skills/{high-end-visual-design → soft}/SKILL.md +1 -3
- package/dist/skills/stitch/DESIGN.md +121 -0
- package/dist/skills/{stitch-design-taste → stitch}/SKILL.md +1 -3
- package/dist/skills/{design-taste-frontend → taste}/SKILL.md +1 -3
- package/dist/skills/{design-taste-frontend-v1 → taste-v1}/SKILL.md +2 -4
- package/package.json +1 -1
|
@@ -6,18 +6,19 @@ Zentui reads optional user configuration from `~/.pi/agent/zentui.json`. Missing
|
|
|
6
6
|
|
|
7
7
|
## `/zentui` settings
|
|
8
8
|
|
|
9
|
-
The interactive `/zentui` menu is split into
|
|
9
|
+
The interactive `/zentui` menu is split into nine component-oriented sections. Use `Tab` and `Shift+Tab` to switch sections:
|
|
10
10
|
|
|
11
11
|
1. **Appearance** — selector-border enablement, style, and colors; icon mode.
|
|
12
12
|
2. **Editor** — enablement, style, colors, model label, border behavior, viewport indicators, settings for the selected editor style, and a static synthetic preview.
|
|
13
13
|
3. **User messages** — enablement, style, colors, and a static synthetic Markdown preview.
|
|
14
|
-
4. **
|
|
15
|
-
5. **
|
|
16
|
-
6. **
|
|
17
|
-
7. **
|
|
18
|
-
8. **
|
|
14
|
+
4. **Thinking (Experimental)** — private Rail, Tree, or Streaming rendering; active Streaming can switch live to Rail or Tree, Rail and Tree can switch live between each other, and the private renderer may break after Pi updates.
|
|
15
|
+
5. **Working line** — ownership, settled Turn summary, spinner and text speeds, optional spinner-color motion, text animation, color source, custom messages, Tool/Elapsed/Thinking time/Tokens segments, and animated preview.
|
|
16
|
+
6. **Footer** — Native, Starship, or Hidden. Starship additionally exposes colors, model label, responsive layout, separator, context style, and path display.
|
|
17
|
+
7. **Segments** — visibility toggles for non-Git Starship segments.
|
|
18
|
+
8. **Git** — Starship Git segment and probe controls.
|
|
19
|
+
9. **Extensions** — Starship extension-status placement and color controls for active keys.
|
|
19
20
|
|
|
20
|
-
Editor, User messages, and Working line retain independent configuration. Editor
|
|
21
|
+
Editor, User messages, Thinking (Experimental), and Working line retain independent configuration. Editor, User-message, and Thinking previews remain visible while their component is disabled. Only the Working-line preview owns an animation timer. Footer-specific rows are shown only while Starship is selected, while Segments, Git, and Extensions remain available for preconfiguration under every Footer style.
|
|
21
22
|
|
|
22
23
|
Free-form values such as custom formats, Opencode metadata formats, raw colors/styles, and inactive extension keys remain JSON-only. Working-line speed accepts validated custom milliseconds in `/zentui`.
|
|
23
24
|
|
|
@@ -99,6 +100,10 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
99
100
|
"labeled": {}
|
|
100
101
|
}
|
|
101
102
|
},
|
|
103
|
+
"thinkingSteps": {
|
|
104
|
+
"enabled": false,
|
|
105
|
+
"mode": "tree"
|
|
106
|
+
},
|
|
102
107
|
"workingLine": {
|
|
103
108
|
"enabled": false,
|
|
104
109
|
"turnSummary": true,
|
|
@@ -267,7 +272,9 @@ Copy this example and change only the values you need. Optional editor source-aw
|
|
|
267
272
|
- `components.editor` owns Editor enablement, `opencode | opencode-copy-friendly | accent-rail | minimalist` style selection, color source, border mode, model label, viewport indicators, and all four style configurations.
|
|
268
273
|
- Editor `modelLabel` uses `id` by default; `name` uses the display name with ID fallback. Footer has an independent `modelLabel` control.
|
|
269
274
|
- `components.userMessages` owns User-message enablement, `framed | framed-copy-friendly | compact | labeled` style selection, and color source. Disabling it delegates byte-for-byte to Pi's native renderer.
|
|
270
|
-
- `components.
|
|
275
|
+
- `components.thinkingSteps` independently owns opt-in **Thinking (Experimental)** display. It defaults to `{ "enabled": false, "mode": "tree" }`; canonical modes are `rail | tree | streaming`. The former persisted `streaming-experimental` value is accepted only as a migration alias and is normalized to `streaming` on save.
|
|
276
|
+
- All three modes decorate Pi's private host renderer and are tested on exact Pi versions 0.80.5, 0.82.1, 0.83.0, 0.84.0, and 0.84.4. Active Streaming can switch live to Rail or Tree, and Rail and Tree can switch live between each other. Entering Streaming from a structural mode, first enable, and re-enable after live disable require restart; live disable restores native thinking. Disabled mode changes only preconfigure.
|
|
277
|
+
- `components.workingLine.enabled` is the sole Working-line ownership switch. Thinking (Experimental) never enables, configures, or owns the Working line and leaves the existing **Thinking time** option unchanged.
|
|
271
278
|
- `components.selectorBorders` owns selector-border enablement, fixed `zentui` style, and color source. Disable it for native Pi behavior.
|
|
272
279
|
- `components.footer` owns `native | starship | hidden` style selection, color source, model label, and Starship options. Hidden installs an empty component with zero rows.
|
|
273
280
|
- Starship's package-version segment reads the project manifest and is distinct from the runtime segment, which reports the installed toolchain.
|
|
@@ -381,6 +388,27 @@ Missing, non-string, or empty values use `$model $provider( $thinking)`. A non
|
|
|
381
388
|
- Disabling styling delegates to Pi's native renderer; native is not a style ID.
|
|
382
389
|
- Zentui intentionally provides no custom `plain` style.
|
|
383
390
|
|
|
391
|
+
## Thinking (Experimental)
|
|
392
|
+
|
|
393
|
+
Rail, Tree, and Streaming share one private `AssistantMessageComponent` wrapper. The saved `{ enabled, mode }` value is read at session start before transcript restoration; disabled startup installs nothing. Once installed and healthy, active Streaming can switch live to Rail or Tree, and Rail and Tree can switch live between each other, without reinstalling the patch. Each supported transition rerenders tracked components once. Selecting Streaming from Rail or Tree saves Streaming but keeps the active structural mode unchanged and reports restart required; it never acquires input or timer resources live. Leaving Streaming releases those resources. If cleanup throws, a requested Rail or Tree mode still becomes active, while disable still restores native children; either successful change warns that Streaming is unavailable for the rest of the session. Entering Streaming from a structural mode, first enable, and re-enable after a live disable require restart, while mode changes when disabled only preconfigure. Shutdown restores native children, exact hidden-state ownership, and the predecessor descriptor. Startup acquisition or private constructor, layout, Markdown identity, parser, theme, rendering, width, or displacement failure uses native thinking. Private APIs may break after any Pi update.
|
|
394
|
+
|
|
395
|
+
Rail parses each native contiguous thinking run and shows every label in that run. Tree shows the latest five in each run; neither aggregates across intervening text or tool blocks. Both follow Pi's thinking visibility. Labels come from headings, top-level list items, and blank-line-separated prose. Complete strict 7-bit CSI SGR styling is stripped before parsing; every other terminal control, unsafe or unstructured content, malformed or over-limit input, unterminated fences/math, and unsupported structure leave that complete run native. Fenced code, Mermaid, display math, and indented nested content remain opaque bodies.
|
|
396
|
+
|
|
397
|
+
Each selected SGR-free label is rendered as Markdown by a fresh Pi `Markdown` with the host child's exact theme, default `thinkingText`/italic style, and transform options. Native emphasis, code, links, HTML, LaTeX, and custom theme/transform callbacks therefore remain authoritative. Host horizontal padding is applied externally. Each label is exactly one terminal row; Pi TUI's ANSI/OSC/grapheme-aware width utilities crop the first rendered row and reserve one cell for `…` only when required. Empty, image, non-text, impossible-width, or throwing output restores the whole native run. Connectors are separate from Markdown and call the current `theme.fg("accent", connector)` every render, so custom themes directly control their appearance. Visible forms are:
|
|
398
|
+
|
|
399
|
+
```text
|
|
400
|
+
│ Thinking ┆ Thinking
|
|
401
|
+
│ First ├─ · Earlier
|
|
402
|
+
│ Latest └─ · Latest
|
|
403
|
+
│ • Open └─ • Open
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Only an actually open thinking phase uses `•`; a text/tool transition or restored completion is settled. Rail and Tree preserve Pi's hidden state and native hidden label. The `/zentui` Mode action offers all three modes, but entering Streaming from Rail or Tree is saved for restart rather than applied live.
|
|
407
|
+
|
|
408
|
+
Streaming keeps the reviewed host-rendered behavior: while open it shows the latest five rendered terminal rows beneath `Thinking 7.1s`; completion folds under `Thought` or current-session `Thought for Ns`. Restored entries have no duration because Pi does not persist a reliable thinking-end timestamp. Only a session started in active Streaming owns its validated configured `app.thinking.toggle` binding and one-second timer. Ctrl+T expands/refolds native reasoning. Startup resource failures and private-shape/render failures use complete native thinking. A cleanup callback that throws while leaving Streaming is contained: Rail or Tree remains active, while Streaming becomes unavailable for that session. Component and timing tracking are bounded to 256; evicted entries are restored natively first.
|
|
409
|
+
|
|
410
|
+
The exact all-mode private matrix covers Pi 0.80.5, 0.82.1, 0.83.0, 0.84.0, and 0.84.4 under dark, light, and current themes, narrow/wide widths and resize; Pi 0.84.4 also has a fullscreen live-transition PTY smoke. Thinking (Experimental) never owns or writes the Working line, including its unchanged **Thinking time** option, and does not own Footer, Editor, widgets, statuses, or model behavior.
|
|
411
|
+
|
|
384
412
|
## Working line
|
|
385
413
|
|
|
386
414
|
When enabled, Zentui owns Pi's complete working-row message and indicator. Five fixed-width spinner presets are available: Braille Orbit, Star Bloom, ASCII Pinwheel, Claude-inspired, and three-cell Pulse.
|
|
@@ -389,7 +417,7 @@ When enabled, Zentui owns Pi's complete working-row message and indicator. Five
|
|
|
389
417
|
|
|
390
418
|
Committed totals stay provider-reported across tool loops, retries, compaction retries, and queued continuations. During a response, live output follows Pi's `↓N` convention whether usage is provider-reported or temporarily estimated. Final usage reconciles atomically; input is never estimated. Labels are sanitized and width-bounded.
|
|
391
419
|
|
|
392
|
-
When Pi settles, the default-on **Turn summary** appends a persistent context-free row such as `Turn took 56s · thought for 10s · ↑7.1k ↓779`. Thought is cumulative wall-clock time from Pi's public thinking stream; overlaps count once and zero is omitted. Output already includes reasoning tokens, so reasoning is not added separately. Summaries always include both token totals, even when live Tokens or Thinking is hidden or zero, and can be disabled without changing historical rows. They use the fixed high style and are inactive while Working line is disabled.
|
|
420
|
+
When Pi settles, the default-on **Turn summary** appends a persistent context-free row such as `Turn took 56s · thought for 10s · ↑7.1k ↓779`. Thought is cumulative wall-clock time from Pi's public thinking stream; overlaps count once and zero is omitted. Output already includes reasoning tokens, so reasoning is not added separately. Summaries always include both token totals, even when live Tokens or **Thinking time** is hidden or zero, and can be disabled without changing historical rows. They use the fixed high style and are inactive while Working line is disabled.
|
|
393
421
|
|
|
394
422
|
Classic and KITT move color across message and segments. **Animate spinner color** optionally includes spinner cells and separator. Static colors the full row uniformly and ignores text speed/spinner-color participation without changing saved values. Spinner glyph motion always remains active.
|
|
395
423
|
|
|
@@ -46,6 +46,7 @@ export type WorkingLineSpinner =
|
|
|
46
46
|
| "claude-inspired"
|
|
47
47
|
| "pulse";
|
|
48
48
|
export type WorkingLineTextAnimation = "classic" | "kitt" | "disabled";
|
|
49
|
+
export type ThinkingStepsMode = "rail" | "tree" | "streaming";
|
|
49
50
|
export type ComponentStyleOwner = "editor" | "userMessages" | "selectorBorders" | "footer";
|
|
50
51
|
export type MinimalistPathDisplayMode = "compact" | "project" | "full";
|
|
51
52
|
export type MinimalistContextFormat = "percent" | "percent-total";
|
|
@@ -250,9 +251,15 @@ export type WorkingLineComponentPatch = Partial<
|
|
|
250
251
|
segments?: Partial<WorkingLineSegmentsConfig>;
|
|
251
252
|
};
|
|
252
253
|
|
|
254
|
+
export type ThinkingStepsComponentConfig = {
|
|
255
|
+
enabled: boolean;
|
|
256
|
+
mode: ThinkingStepsMode;
|
|
257
|
+
};
|
|
258
|
+
|
|
253
259
|
export type ComponentsConfig = {
|
|
254
260
|
editor: EditorComponentConfig;
|
|
255
261
|
userMessages: UserMessagesComponentConfig;
|
|
262
|
+
thinkingSteps: ThinkingStepsComponentConfig;
|
|
256
263
|
workingLine: WorkingLineComponentConfig;
|
|
257
264
|
selectorBorders: SelectorBordersComponentConfig;
|
|
258
265
|
footer: FooterComponentConfig;
|
|
@@ -498,6 +505,7 @@ const defaultComponents: ComponentsConfig = {
|
|
|
498
505
|
colorSource: "theme",
|
|
499
506
|
styles: { framed: {}, "framed-copy-friendly": {}, compact: {}, labeled: {} },
|
|
500
507
|
},
|
|
508
|
+
thinkingSteps: { enabled: false, mode: "tree" },
|
|
501
509
|
workingLine: {
|
|
502
510
|
enabled: true,
|
|
503
511
|
turnSummary: true,
|
|
@@ -1194,6 +1202,7 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1194
1202
|
const userMessages = recordValue(components.userMessages);
|
|
1195
1203
|
const userMessageStyles = recordValue(userMessages.styles);
|
|
1196
1204
|
const framed = recordValue(userMessageStyles.framed);
|
|
1205
|
+
const thinkingSteps = recordValue(components.thinkingSteps);
|
|
1197
1206
|
const workingLine = recordValue(components.workingLine);
|
|
1198
1207
|
const workingLineMessages = recordValue(workingLine.messages);
|
|
1199
1208
|
const workingLineSegments = recordValue(workingLine.segments);
|
|
@@ -1301,6 +1310,15 @@ function resolveComponents(config: ConfigRecord): ComponentsConfig {
|
|
|
1301
1310
|
labeled: {},
|
|
1302
1311
|
},
|
|
1303
1312
|
},
|
|
1313
|
+
thinkingSteps: {
|
|
1314
|
+
enabled: parseBoolean(thinkingSteps.enabled, defaultComponents.thinkingSteps.enabled),
|
|
1315
|
+
mode:
|
|
1316
|
+
thinkingSteps.mode === "rail" || thinkingSteps.mode === "tree"
|
|
1317
|
+
? thinkingSteps.mode
|
|
1318
|
+
: thinkingSteps.mode === "streaming" || thinkingSteps.mode === "streaming-experimental"
|
|
1319
|
+
? "streaming"
|
|
1320
|
+
: defaultComponents.thinkingSteps.mode,
|
|
1321
|
+
},
|
|
1304
1322
|
workingLine: {
|
|
1305
1323
|
enabled: parseBoolean(workingLine.enabled, defaultComponents.workingLine.enabled),
|
|
1306
1324
|
turnSummary: parseBoolean(workingLine.turnSummary, defaultComponents.workingLine.turnSummary),
|
|
@@ -1746,6 +1764,17 @@ export function saveUserMessagesComponentPatch(
|
|
|
1746
1764
|
);
|
|
1747
1765
|
}
|
|
1748
1766
|
|
|
1767
|
+
export function saveThinkingStepsComponentPatch(
|
|
1768
|
+
patch: Partial<ThinkingStepsComponentConfig>,
|
|
1769
|
+
path = configPath,
|
|
1770
|
+
): PolishedTuiConfig {
|
|
1771
|
+
return saveComponentsMutation((components) => {
|
|
1772
|
+
const component = components.thinkingSteps;
|
|
1773
|
+
if (patch.enabled !== undefined) component.enabled = patch.enabled;
|
|
1774
|
+
if (patch.mode !== undefined) component.mode = patch.mode;
|
|
1775
|
+
}, path);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1749
1778
|
export function saveWorkingLineComponentPatch(
|
|
1750
1779
|
patch: WorkingLineComponentPatch,
|
|
1751
1780
|
path = configPath,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
type AccentRailEditorStyleConfig,
|
|
16
16
|
type ContextStyle,
|
|
17
|
+
defaultConfig,
|
|
17
18
|
type EditorComponentConfig,
|
|
18
19
|
type ExtensionStatusColorMode,
|
|
19
20
|
type ExtensionStatusPlacement,
|
|
@@ -46,8 +47,10 @@ import {
|
|
|
46
47
|
savePolishedEditorStylePatch,
|
|
47
48
|
saveSelectorBordersComponentPatch,
|
|
48
49
|
saveStarshipFooterStylePatch,
|
|
50
|
+
saveThinkingStepsComponentPatch,
|
|
49
51
|
saveUserMessagesComponentPatch,
|
|
50
52
|
saveWorkingLineComponentPatch,
|
|
53
|
+
type ThinkingStepsComponentConfig,
|
|
51
54
|
type UserMessagesComponentConfig,
|
|
52
55
|
type WorkingLineComponentPatch,
|
|
53
56
|
type ZentuiConfig,
|
|
@@ -86,6 +89,7 @@ import { SessionLifecycle } from "./session-lifecycle";
|
|
|
86
89
|
import { registerZentuiSettingsCommand } from "./settings-command";
|
|
87
90
|
import { createInitialState, type FooterState, modelLabelFor, syncState } from "./state";
|
|
88
91
|
import { resolveFooterTelemetry } from "./telemetry";
|
|
92
|
+
import { ThinkingExperimentalController } from "./thinking-experimental";
|
|
89
93
|
import { PolishedEditor, WrappedPolishedEditor } from "./ui";
|
|
90
94
|
import { installUserMessageStyle, removeUserMessageStyle } from "./user-message";
|
|
91
95
|
import {
|
|
@@ -180,7 +184,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
180
184
|
const sessionLifecycle = new SessionLifecycle();
|
|
181
185
|
const editorOwnerToken = Symbol("zentui-editor-owner");
|
|
182
186
|
|
|
183
|
-
let currentConfig: PolishedTuiConfig =
|
|
187
|
+
let currentConfig: PolishedTuiConfig = structuredClone(defaultConfig);
|
|
184
188
|
// Keep the capability guard defensive for hosts with incomplete extension APIs.
|
|
185
189
|
if (typeof pi.registerEntryRenderer === "function") {
|
|
186
190
|
pi.registerEntryRenderer(TURN_SUMMARY_ENTRY_TYPE, (entry, options, theme) =>
|
|
@@ -278,6 +282,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
278
282
|
requestFooterRender?.();
|
|
279
283
|
requestEditorRender?.();
|
|
280
284
|
};
|
|
285
|
+
const thinkingExperimental = new ThinkingExperimentalController(
|
|
286
|
+
() => currentConfig.components.thinkingSteps,
|
|
287
|
+
);
|
|
288
|
+
const thinkingStepsCapability = {
|
|
289
|
+
get state() {
|
|
290
|
+
return thinkingExperimental.state;
|
|
291
|
+
},
|
|
292
|
+
};
|
|
281
293
|
const liveContext = new LiveContextController(sessionLifecycle, refresh);
|
|
282
294
|
const getActiveTheme = () => activeTheme;
|
|
283
295
|
const getCurrentConfig = () => currentConfig;
|
|
@@ -1028,7 +1040,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1028
1040
|
const staleFooterOwner = ctxFooterOwner(ctx);
|
|
1029
1041
|
if (typeof staleFooterOwner === "symbol") installedFooterToken = staleFooterOwner;
|
|
1030
1042
|
ensureConfigExists();
|
|
1031
|
-
currentConfig = loadConfig();
|
|
1032
1043
|
syncFooterState(ctx);
|
|
1033
1044
|
stopProjectRefresh();
|
|
1034
1045
|
|
|
@@ -1136,6 +1147,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
1136
1147
|
|
|
1137
1148
|
pi.on("session_start", async (_event, ctx) => {
|
|
1138
1149
|
const lifecycleGeneration = sessionLifecycle.start();
|
|
1150
|
+
// Reload synchronously so private ownership uses this session's disk snapshot before
|
|
1151
|
+
// any await or transcript restoration.
|
|
1152
|
+
currentConfig = loadConfig();
|
|
1153
|
+
thinkingExperimental.startSession(ctx);
|
|
1139
1154
|
const layoutInstallSerial = ++accentRailLayoutPatchInstallSerial;
|
|
1140
1155
|
cleanupAccentRailLayoutPatch();
|
|
1141
1156
|
cleanupAccentRailLayoutPatch = () => {};
|
|
@@ -1216,6 +1231,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
1216
1231
|
if (patch.enabled !== undefined || patch.style !== undefined) reconcileUserMessages();
|
|
1217
1232
|
refresh();
|
|
1218
1233
|
},
|
|
1234
|
+
thinkingStepsCapability,
|
|
1235
|
+
setThinkingStepsComponent(
|
|
1236
|
+
patch: Partial<ThinkingStepsComponentConfig>,
|
|
1237
|
+
_ctx: ExtensionContext,
|
|
1238
|
+
) {
|
|
1239
|
+
currentConfig = saveThinkingStepsComponentPatch(patch);
|
|
1240
|
+
return thinkingExperimental.reconcile();
|
|
1241
|
+
},
|
|
1219
1242
|
setWorkingLineComponent(patch: WorkingLineComponentPatch, ctx: ExtensionContext) {
|
|
1220
1243
|
currentConfig = saveWorkingLineComponentPatch(patch);
|
|
1221
1244
|
return workingLine.reconcile(ctx);
|
|
@@ -1303,6 +1326,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1303
1326
|
});
|
|
1304
1327
|
|
|
1305
1328
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
1329
|
+
thinkingExperimental.shutdown();
|
|
1306
1330
|
liveContext.clear();
|
|
1307
1331
|
interactionMetrics.shutdown();
|
|
1308
1332
|
workingLine.dispose(ctx);
|
|
@@ -1314,6 +1338,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
1314
1338
|
refreshInteractiveState(ctx, true);
|
|
1315
1339
|
};
|
|
1316
1340
|
|
|
1341
|
+
pi.on("message_start", (event) => thinkingExperimental.beginMessage(event));
|
|
1342
|
+
|
|
1317
1343
|
pi.on("agent_start", (event, ctx) => {
|
|
1318
1344
|
liveContext.clear();
|
|
1319
1345
|
const { interactionStarted } = interactionMetrics.agentStart();
|
|
@@ -1326,6 +1352,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1326
1352
|
workingLine.startTurn(ctx);
|
|
1327
1353
|
});
|
|
1328
1354
|
pi.on("agent_end", (event, ctx) => {
|
|
1355
|
+
thinkingExperimental.endAgent();
|
|
1329
1356
|
liveContext.clear();
|
|
1330
1357
|
const displayTokens = interactionMetrics.currentDisplayTokens();
|
|
1331
1358
|
interactionMetrics.agentEnd();
|
|
@@ -1342,6 +1369,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1342
1369
|
pi.on("thinking_level_select", syncInteractiveState);
|
|
1343
1370
|
pi.on("session_info_changed", syncInteractiveState);
|
|
1344
1371
|
pi.on("message_update", (event, ctx) => {
|
|
1372
|
+
thinkingExperimental.updateMessage(event);
|
|
1345
1373
|
liveContext.update(event.message);
|
|
1346
1374
|
const metrics = interactionMetrics.messageUpdate(
|
|
1347
1375
|
event.message,
|
|
@@ -1352,6 +1380,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1352
1380
|
}
|
|
1353
1381
|
});
|
|
1354
1382
|
pi.on("message_end", (event, ctx) => {
|
|
1383
|
+
thinkingExperimental.endMessage(event);
|
|
1355
1384
|
const result = interactionMetrics.messageEnd(event.message);
|
|
1356
1385
|
if (result.status === "accepted") {
|
|
1357
1386
|
workingLine.updateMetrics(result.displayTokens, interactionMetrics.currentThought(), ctx);
|
|
@@ -3,7 +3,8 @@ export const ZENTUI_PROTOTYPE_PATCH_REGISTRY = Symbol.for("pi-zentui.prototype-p
|
|
|
3
3
|
type PrototypePatchAdapter =
|
|
4
4
|
| "user-message-render"
|
|
5
5
|
| "user-message-invalidate"
|
|
6
|
-
| "selector-border-render"
|
|
6
|
+
| "selector-border-render"
|
|
7
|
+
| "thinking-experimental-update-content";
|
|
7
8
|
|
|
8
9
|
type PrototypeMethod = (this: unknown, ...args: unknown[]) => unknown;
|
|
9
10
|
|
|
@@ -18,10 +19,13 @@ type PatchBehavior = (invocation: PatchInvocation) => unknown;
|
|
|
18
19
|
type Registration = {
|
|
19
20
|
token: symbol;
|
|
20
21
|
behavior?: PatchBehavior;
|
|
22
|
+
onDisplaced?: () => void;
|
|
21
23
|
};
|
|
22
24
|
|
|
25
|
+
type PatchMethod = "render" | "invalidate" | "updateContent";
|
|
26
|
+
|
|
23
27
|
type PatchRecord = {
|
|
24
|
-
method:
|
|
28
|
+
method: PatchMethod;
|
|
25
29
|
predecessor: PrototypeMethod;
|
|
26
30
|
predecessorDescriptor?: PropertyDescriptor;
|
|
27
31
|
wrapper: PrototypeMethod;
|
|
@@ -48,10 +52,20 @@ function registryFor(target: PatchTarget): PatchRegistry {
|
|
|
48
52
|
return registry;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
function deactivateRecord(record: PatchRecord): void {
|
|
55
|
+
function deactivateRecord(record: PatchRecord, displaced = false): void {
|
|
52
56
|
if (!record.registration) return;
|
|
53
|
-
|
|
57
|
+
const registration = record.registration;
|
|
58
|
+
const onDisplaced = registration.onDisplaced;
|
|
59
|
+
registration.behavior = undefined;
|
|
60
|
+
registration.onDisplaced = undefined;
|
|
54
61
|
record.registration = undefined;
|
|
62
|
+
if (displaced) {
|
|
63
|
+
try {
|
|
64
|
+
onDisplaced?.();
|
|
65
|
+
} catch {
|
|
66
|
+
// Registration handoff must not prevent the newer owner from installing.
|
|
67
|
+
}
|
|
68
|
+
}
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
function restorePredecessor(target: PatchTarget, record: PatchRecord): void {
|
|
@@ -77,15 +91,17 @@ function installWrapper(target: PatchTarget, record: PatchRecord): void {
|
|
|
77
91
|
});
|
|
78
92
|
}
|
|
79
93
|
|
|
94
|
+
export type PrototypePatchRegistration = (() => void) & Readonly<{ token: symbol }>;
|
|
95
|
+
|
|
80
96
|
function createCleanup(
|
|
81
97
|
target: PatchTarget,
|
|
82
98
|
adapter: PrototypePatchAdapter,
|
|
83
99
|
registry: PatchRegistry,
|
|
84
100
|
record: PatchRecord,
|
|
85
101
|
token: symbol,
|
|
86
|
-
):
|
|
102
|
+
): PrototypePatchRegistration {
|
|
87
103
|
let cleaned = false;
|
|
88
|
-
|
|
104
|
+
const cleanup = () => {
|
|
89
105
|
if (cleaned) return;
|
|
90
106
|
cleaned = true;
|
|
91
107
|
if (record.registration?.token !== token) return;
|
|
@@ -97,14 +113,16 @@ function createCleanup(
|
|
|
97
113
|
registry.delete(adapter);
|
|
98
114
|
if (registry.size === 0) delete target[ZENTUI_PROTOTYPE_PATCH_REGISTRY];
|
|
99
115
|
};
|
|
116
|
+
return Object.assign(cleanup, { token });
|
|
100
117
|
}
|
|
101
118
|
|
|
102
119
|
export function installPrototypePatch(
|
|
103
120
|
targetValue: object,
|
|
104
|
-
method:
|
|
121
|
+
method: PatchMethod,
|
|
105
122
|
adapter: PrototypePatchAdapter,
|
|
106
123
|
behavior: PatchBehavior,
|
|
107
|
-
|
|
124
|
+
onDisplaced?: () => void,
|
|
125
|
+
): PrototypePatchRegistration {
|
|
108
126
|
const target = targetValue as PatchTarget;
|
|
109
127
|
const registry = registryFor(target);
|
|
110
128
|
let record = registry.get(adapter);
|
|
@@ -141,17 +159,43 @@ export function installPrototypePatch(
|
|
|
141
159
|
}
|
|
142
160
|
record = nextRecord;
|
|
143
161
|
registry.set(adapter, record);
|
|
144
|
-
if (displacedRecord && displacedRecord !== record) deactivateRecord(displacedRecord);
|
|
162
|
+
if (displacedRecord && displacedRecord !== record) deactivateRecord(displacedRecord, true);
|
|
145
163
|
}
|
|
146
164
|
|
|
165
|
+
const previousRegistration = record.registration;
|
|
147
166
|
const token = Symbol(adapter);
|
|
148
|
-
record.registration = { token, behavior };
|
|
167
|
+
record.registration = { token, behavior, onDisplaced };
|
|
168
|
+
if (previousRegistration) {
|
|
169
|
+
previousRegistration.behavior = undefined;
|
|
170
|
+
try {
|
|
171
|
+
previousRegistration.onDisplaced?.();
|
|
172
|
+
} catch {
|
|
173
|
+
// Registration handoff must not prevent the newer owner from installing.
|
|
174
|
+
}
|
|
175
|
+
previousRegistration.onDisplaced = undefined;
|
|
176
|
+
}
|
|
149
177
|
return createCleanup(target, adapter, registry, record, token);
|
|
150
178
|
}
|
|
151
179
|
|
|
180
|
+
export function isPrototypePatchCurrent(
|
|
181
|
+
targetValue: object,
|
|
182
|
+
method: PatchMethod,
|
|
183
|
+
adapter: PrototypePatchAdapter,
|
|
184
|
+
token?: symbol,
|
|
185
|
+
): boolean {
|
|
186
|
+
const target = targetValue as PatchTarget;
|
|
187
|
+
const record = existingRegistry(target)?.get(adapter);
|
|
188
|
+
return Boolean(
|
|
189
|
+
record &&
|
|
190
|
+
record.method === method &&
|
|
191
|
+
target[method] === record.wrapper &&
|
|
192
|
+
(token === undefined || record.registration?.token === token),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
152
196
|
export function removePrototypePatch(
|
|
153
197
|
targetValue: object,
|
|
154
|
-
method:
|
|
198
|
+
method: PatchMethod,
|
|
155
199
|
adapter: PrototypePatchAdapter,
|
|
156
200
|
): void {
|
|
157
201
|
const target = targetValue as PatchTarget;
|
|
@@ -45,6 +45,8 @@ import {
|
|
|
45
45
|
type PolishedTuiConfig,
|
|
46
46
|
type SelectorBordersComponentConfig,
|
|
47
47
|
type SeparatorStyle,
|
|
48
|
+
type ThinkingStepsComponentConfig,
|
|
49
|
+
type ThinkingStepsMode,
|
|
48
50
|
type UserMessageStyle,
|
|
49
51
|
type UserMessagesComponentConfig,
|
|
50
52
|
type WorkingLineComponentPatch,
|
|
@@ -56,10 +58,12 @@ import { isIconMode } from "./icons";
|
|
|
56
58
|
import type { SessionLifecycle } from "./session-lifecycle";
|
|
57
59
|
import {
|
|
58
60
|
renderEditorSettingsPreview,
|
|
61
|
+
renderThinkingStepsSettingsPreview,
|
|
59
62
|
renderUserMessageSettingsPreview,
|
|
60
63
|
SETTINGS_PREVIEW_MAX_WIDTH,
|
|
61
64
|
} from "./settings-previews";
|
|
62
65
|
import { EDITOR_BORDER_STYLE, renderChromeBorder, safeThemeFg } from "./style";
|
|
66
|
+
import { formatThinkingStatus, thinkingStatusLabels } from "./thinking-status";
|
|
63
67
|
import {
|
|
64
68
|
buildWorkingLinePreviewFrames,
|
|
65
69
|
normalizeWorkingLineMessages,
|
|
@@ -132,11 +136,22 @@ const speedValues = (presets: readonly { label: string }[]) => [
|
|
|
132
136
|
"Custom…",
|
|
133
137
|
];
|
|
134
138
|
const workingLineTextAnimationValues: WorkingLineTextAnimation[] = ["classic", "kitt", "disabled"];
|
|
139
|
+
const thinkingStepsModeLabels: Record<ThinkingStepsMode, string> = {
|
|
140
|
+
rail: "Rail",
|
|
141
|
+
tree: "Tree",
|
|
142
|
+
streaming: "Streaming",
|
|
143
|
+
};
|
|
144
|
+
const thinkingStepsModeValues = (startupMode: ThinkingStepsMode): string[] => {
|
|
145
|
+
if (startupMode === "streaming") return ["Streaming", "Tree", "Rail"];
|
|
146
|
+
if (startupMode === "rail") return ["Rail", "Tree", "Streaming"];
|
|
147
|
+
return ["Tree", "Rail", "Streaming"];
|
|
148
|
+
};
|
|
135
149
|
|
|
136
150
|
const settingsSections = [
|
|
137
151
|
"appearance",
|
|
138
152
|
"editor",
|
|
139
153
|
"userMessages",
|
|
154
|
+
"thinkingSteps",
|
|
140
155
|
"workingLine",
|
|
141
156
|
"footer",
|
|
142
157
|
"segments",
|
|
@@ -164,6 +179,37 @@ type SettingsOutcome =
|
|
|
164
179
|
| "edit-working-line-spinner-speed"
|
|
165
180
|
| "edit-working-line-text-speed";
|
|
166
181
|
|
|
182
|
+
type ThinkingControllerState = Readonly<{
|
|
183
|
+
available: boolean;
|
|
184
|
+
rendererAvailable?: boolean;
|
|
185
|
+
streamingAvailable?: boolean;
|
|
186
|
+
streamingPoisoned?: boolean;
|
|
187
|
+
active: boolean;
|
|
188
|
+
activeMode?: ThinkingStepsMode;
|
|
189
|
+
startup: Readonly<ThinkingStepsComponentConfig>;
|
|
190
|
+
displaced: boolean;
|
|
191
|
+
restartRequired: boolean;
|
|
192
|
+
reason?: string;
|
|
193
|
+
}>;
|
|
194
|
+
|
|
195
|
+
type ThinkingStepsSettingsCapability =
|
|
196
|
+
| Readonly<{ available: boolean }>
|
|
197
|
+
| Readonly<{ readonly state: ThinkingControllerState }>;
|
|
198
|
+
|
|
199
|
+
function experimentalThinkingCapability(
|
|
200
|
+
capability: ThinkingStepsSettingsCapability,
|
|
201
|
+
): ThinkingControllerState {
|
|
202
|
+
return "state" in capability
|
|
203
|
+
? capability.state
|
|
204
|
+
: {
|
|
205
|
+
available: capability.available,
|
|
206
|
+
active: false,
|
|
207
|
+
startup: { enabled: false, mode: "tree" },
|
|
208
|
+
displaced: false,
|
|
209
|
+
restartRequired: false,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
167
213
|
type SettingsCommandDeps = {
|
|
168
214
|
sessionLifecycle: SessionLifecycle;
|
|
169
215
|
getConfig: () => PolishedTuiConfig;
|
|
@@ -176,6 +222,11 @@ type SettingsCommandDeps = {
|
|
|
176
222
|
setAccentRail: (patch: Partial<AccentRailEditorStyleConfig>, ctx: ExtensionContext) => void;
|
|
177
223
|
setMinimalist: (patch: Partial<MinimalistConfig>, ctx: ExtensionContext) => void;
|
|
178
224
|
setUserMessagesComponent: (patch: UserMessagesPatch, ctx: ExtensionContext) => void;
|
|
225
|
+
thinkingStepsCapability: ThinkingStepsSettingsCapability;
|
|
226
|
+
setThinkingStepsComponent: (
|
|
227
|
+
patch: Partial<ThinkingStepsComponentConfig>,
|
|
228
|
+
ctx: ExtensionContext,
|
|
229
|
+
) => ApplyResult;
|
|
179
230
|
setWorkingLineComponent: (patch: WorkingLineComponentPatch, ctx: ExtensionContext) => ApplyResult;
|
|
180
231
|
setSelectorBordersComponent: (
|
|
181
232
|
patch: Partial<SelectorBordersComponentConfig>,
|
|
@@ -210,6 +261,7 @@ const sectionLabels: Record<SettingsSection, string> = {
|
|
|
210
261
|
appearance: "Appearance",
|
|
211
262
|
editor: "Editor",
|
|
212
263
|
userMessages: "User messages",
|
|
264
|
+
thinkingSteps: "Thinking (Experimental)",
|
|
213
265
|
workingLine: "Working line",
|
|
214
266
|
footer: "Footer",
|
|
215
267
|
segments: "Segments",
|
|
@@ -308,6 +360,11 @@ function userMessageStyleId(label: string): UserMessageStyle | undefined {
|
|
|
308
360
|
([, value]) => value === label,
|
|
309
361
|
)?.[0];
|
|
310
362
|
}
|
|
363
|
+
function thinkingStepsModeId(label: string): ThinkingStepsMode | undefined {
|
|
364
|
+
return (Object.entries(thinkingStepsModeLabels) as Array<[ThinkingStepsMode, string]>).find(
|
|
365
|
+
([, value]) => value === label,
|
|
366
|
+
)?.[0];
|
|
367
|
+
}
|
|
311
368
|
function workingLineSpinnerId(label: string): WorkingLineSpinner | undefined {
|
|
312
369
|
return (Object.entries(workingLineSpinnerLabels) as Array<[WorkingLineSpinner, string]>).find(
|
|
313
370
|
([, value]) => value === label,
|
|
@@ -610,6 +667,32 @@ function buildUserMessagesItems(config: PolishedTuiConfig): SettingItem[] {
|
|
|
610
667
|
},
|
|
611
668
|
];
|
|
612
669
|
}
|
|
670
|
+
function buildThinkingStepsItems(
|
|
671
|
+
config: PolishedTuiConfig,
|
|
672
|
+
capability: ThinkingStepsSettingsCapability,
|
|
673
|
+
): SettingItem[] {
|
|
674
|
+
const thinkingSteps = config.components.thinkingSteps;
|
|
675
|
+
const controller = experimentalThinkingCapability(capability);
|
|
676
|
+
const status = formatThinkingStatus(thinkingStatusLabels(thinkingSteps, controller));
|
|
677
|
+
const enabledDescription = `${status} Live switching supports Streaming → Rail/Tree and Rail ↔ Tree. Entering Streaming, first enable, and re-enable after live disable require restart. Private renderer may break after Pi updates.`;
|
|
678
|
+
return [
|
|
679
|
+
{
|
|
680
|
+
id: "thinkingStepsEnabled",
|
|
681
|
+
label: "Enabled",
|
|
682
|
+
description: enabledDescription,
|
|
683
|
+
currentValue: featureValue(thinkingSteps.enabled),
|
|
684
|
+
values: featureStateValues,
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
id: "thinkingStepsMode",
|
|
688
|
+
label: "Mode",
|
|
689
|
+
description: `${status} Rail shows every parsed label; Tree shows the latest five per contiguous run; both follow Pi thinking visibility, and unsafe or unstructured content remains native. Streaming folds to the latest five host-rendered rows and owns the configured thinking toggle only when active. Incompatibility uses native thinking.`,
|
|
690
|
+
currentValue: thinkingStepsModeLabels[thinkingSteps.mode],
|
|
691
|
+
values: thinkingStepsModeValues(controller.startup.mode),
|
|
692
|
+
},
|
|
693
|
+
];
|
|
694
|
+
}
|
|
695
|
+
|
|
613
696
|
function buildWorkingLineItems(config: PolishedTuiConfig): SettingItem[] {
|
|
614
697
|
const workingLine = config.components.workingLine;
|
|
615
698
|
const staticText = workingLine.textAnimation === "disabled";
|
|
@@ -700,7 +783,7 @@ function buildWorkingLineItems(config: PolishedTuiConfig): SettingItem[] {
|
|
|
700
783
|
},
|
|
701
784
|
{
|
|
702
785
|
id: "workingLineThought",
|
|
703
|
-
label: "Thinking",
|
|
786
|
+
label: "Thinking time",
|
|
704
787
|
description: "Show cumulative wall-clock thinking time and active updates.",
|
|
705
788
|
currentValue: featureValue(workingLine.segments.thought),
|
|
706
789
|
values: featureStateValues,
|
|
@@ -957,6 +1040,7 @@ function buildSectionItems(
|
|
|
957
1040
|
section: SettingsSection,
|
|
958
1041
|
config: PolishedTuiConfig,
|
|
959
1042
|
active: ReadonlyMap<string, string>,
|
|
1043
|
+
thinkingStepsCapability: ThinkingStepsSettingsCapability,
|
|
960
1044
|
): SettingItem[] {
|
|
961
1045
|
switch (section) {
|
|
962
1046
|
case "appearance":
|
|
@@ -977,6 +1061,8 @@ function buildSectionItems(
|
|
|
977
1061
|
];
|
|
978
1062
|
case "userMessages":
|
|
979
1063
|
return buildUserMessagesItems(config);
|
|
1064
|
+
case "thinkingSteps":
|
|
1065
|
+
return buildThinkingStepsItems(config, thinkingStepsCapability);
|
|
980
1066
|
case "workingLine":
|
|
981
1067
|
return buildWorkingLineItems(config);
|
|
982
1068
|
case "footer":
|
|
@@ -1195,9 +1281,10 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
|
|
|
1195
1281
|
};
|
|
1196
1282
|
const notifyChange = (label: string, value: string, result?: ApplyResult) => {
|
|
1197
1283
|
deps.requestRender();
|
|
1284
|
+
const detail = result?.reason?.trim();
|
|
1198
1285
|
ctx.ui.notify(
|
|
1199
|
-
`${label}: ${value}${result && !result.applied ?
|
|
1200
|
-
"info",
|
|
1286
|
+
`${label}: ${value}${detail ? ` (${detail})` : result && !result.applied ? " (reload Pi to apply this change)" : ""}`,
|
|
1287
|
+
result && (!result.applied || detail) ? "warning" : "info",
|
|
1201
1288
|
);
|
|
1202
1289
|
startPreview();
|
|
1203
1290
|
tui.requestRender();
|
|
@@ -1220,6 +1307,7 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
|
|
|
1220
1307
|
activeSection,
|
|
1221
1308
|
deps.getConfig(),
|
|
1222
1309
|
deps.getActiveExtensionStatuses(),
|
|
1310
|
+
deps.thinkingStepsCapability,
|
|
1223
1311
|
);
|
|
1224
1312
|
const list = new SettingsList(
|
|
1225
1313
|
items,
|
|
@@ -1362,6 +1450,23 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
|
|
|
1362
1450
|
notifyChange("Message colors", newValue);
|
|
1363
1451
|
return;
|
|
1364
1452
|
}
|
|
1453
|
+
if (id === "thinkingStepsEnabled" && enabled !== undefined) {
|
|
1454
|
+
const result = deps.setThinkingStepsComponent({ enabled }, ctx);
|
|
1455
|
+
settingsList = makeSettingsList("thinkingStepsEnabled");
|
|
1456
|
+
notifyChange("Thinking (Experimental)", newValue, result);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const selectedThinkingStepsMode =
|
|
1460
|
+
id === "thinkingStepsMode" ? thinkingStepsModeId(newValue) : undefined;
|
|
1461
|
+
if (selectedThinkingStepsMode) {
|
|
1462
|
+
const result = deps.setThinkingStepsComponent(
|
|
1463
|
+
{ mode: selectedThinkingStepsMode },
|
|
1464
|
+
ctx,
|
|
1465
|
+
);
|
|
1466
|
+
settingsList = makeSettingsList("thinkingStepsMode");
|
|
1467
|
+
notifyChange("Thinking (Experimental)", newValue, result);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1365
1470
|
if (id === "workingLineEnabled" && enabled !== undefined) {
|
|
1366
1471
|
const result = deps.setWorkingLineComponent({ enabled }, ctx);
|
|
1367
1472
|
settingsList.updateValue(id, newValue);
|
|
@@ -1661,6 +1766,13 @@ export function registerZentuiSettingsCommand(pi: ExtensionAPI, deps: SettingsCo
|
|
|
1661
1766
|
return renderEditorSettingsPreview(deps.getConfig(), theme, previewWidth);
|
|
1662
1767
|
if (activeSection === "userMessages")
|
|
1663
1768
|
return renderUserMessageSettingsPreview(deps.getConfig(), theme, previewWidth);
|
|
1769
|
+
if (activeSection === "thinkingSteps")
|
|
1770
|
+
return renderThinkingStepsSettingsPreview(
|
|
1771
|
+
deps.getConfig(),
|
|
1772
|
+
theme,
|
|
1773
|
+
previewWidth,
|
|
1774
|
+
deps.thinkingStepsCapability,
|
|
1775
|
+
);
|
|
1664
1776
|
if (activeSection === "workingLine" && preview && preview.frames.length > 0)
|
|
1665
1777
|
return [
|
|
1666
1778
|
truncateToWidth(
|