Skip to content

fix(composer): render skills as atomic inline book tags - #6663

Merged
M4n5ter merged 2 commits into
rust-previewfrom
fix/skill-books
Nov 6, 2026
Merged

M4n5ter merged 2 commits into
rust-previewfrom
fix/skill-books

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Summary

Render skill invocations as inline book tags in both the composer and sent messages, using the existing Lucide icons. Skills keep their position among prose and behave as complete units when selected, deleted, copied or restored by undo. Copied and submitted content retains the canonical /skill:name syntax.

  • Use NSH RichEditor with a product-owned plain-text schema because AppKit's native input does not implement skill tokens. Preserve completion offsets, source addresses, draft resets and scrolling.
  • Preserve native paste, file drops, IME composition, application shortcuts and Tab/Shift+Tab navigation. Clicking editor whitespace restores focus without changing the selection.
  • Fix NSH defects in composition key capture, hidden input focus, whitespace clicks, line-edge movement after Select All, and shortcut dispatch during focus changes.
  • Home/End follow RichEditor's line-start/line-end behavior.

Inline skill book in the composer after a large paste

Plugin API

ComposerFocusHandle now requires bindKey(key: string, action: () => void, options?: { fallback?: boolean }): () => void so composer implementations can route application shortcuts through their editor. The bundled composer and plugin authoring example are updated.

Verification

  • Workbench/UI build unit tests: 19 passed; native registration consumer tests: 2 passed.
  • Terminal and desktop interaction tests: 40 passed, covering completion, atomic deletion, copy/undo, Tab navigation, IME, file paste/drop, draft isolation and submission.
  • Workbench JavaScript tests: 106 passed.
  • Fresh generated UI declarations and plugin SDK acceptance type checks passed.
  • Workbench/UI build Clippy (--all-targets --all-features, warnings denied), documentation, formatting and diff checks passed.

macOS AppKit has not received on-device verification.

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex implemented the changes and regression tests.

Checklist

  • Tests cover the change and fail without it
  • Format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

Use the existing RichEditor for inline skill atoms in drafts and sent
messages, preserving canonical source text and whole-node editing.
Keep completion, clipboard, IME and application shortcuts integrated.

Fix reproduced NSH focus, composition and shortcut routing faults.

Generated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I reviewed all 30 changed files at b5e02cb, including the composer/message adapters, source-address projection, native key routing and plugin-authoring example. I found two P2 issues:

  1. A skill atom survives after ordinary editing invalidates its invocation boundary (composer_input/model.rs:281–315). Starting with a confirmed /skill:review atom, move before it and type x. The source becomes x/skill:review, for which both the editor grammar and the host invocation scanner find no skill. tokenize only adds/replaces matching tokens and leaves the old atom intact. It still renders as a skill and Backspace after it deletes the entire invocation. I reproduced this using the unchanged production model against the actual NSH editor-state/core crates. A freshly constructed document with the identical final text correctly has only plain text. Retokenization needs to turn existing atoms whose current surrounding source no longer matches into text, while preserving selection and undo.

  2. Existing terminal component fixtures cannot bundle the new composer (SkillInput.tsx:20). The new unconditional maka/host import is registered in production and the new workbench fixture, but existing registries in terminal-shell/tests/real_host/components.rs:45–60 and terminal-shell/src/terminal/ui.rs:608–623 only expose host. The current CI logs fail with `maka/host` has no export `ComposerInput` across all six CLI partitions and both rest-1 partitions. These are actual bundle errors at the new import, not inferred timeout causes. Register the real component and state class through a shared accessible fixture registry, and rerun those existing tests. The production registration alone does not repair the test registries.

Local verification: both committed JavaScript skill-message tests and all six committed Rust model tests passed. The Rust model ran from a byte-identical source copy in an isolated package using this head's NSH core/base/macros; I limited the probe workspace and removed unrelated development dependencies/codec patch, without changing model or dependency Rust source. The additional edit/deletion sequence and fresh-document control produced the first finding. This was not a native desktop run. I have not independently run the full workbench/GPUI suites or macOS AppKit acceptance; the PR's broader local results remain the author's results.

merge-tree against rust-preview@41767ca7 succeeds. CI 42176376971 checks out synthetic merge d061368 into 7216229 and is red. Native7 repeats the separately established #6655 instruction-ack fixture failure. Additional CLI/Desktop waits are present; I have not assigned them to either finding without a separate causal check. No protocol or database migration changes. No approval or merge performed.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

let caret = projection.source_at(state.selection().head()) as usize;
let anchor = projection.source_at(state.selection().anchor()) as usize;
let mut replacements = Vec::new();
for range in token_ranges(&projection.source) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Remove skill atoms when edits invalidate their source boundary

This loop only considers current matches, so existing atoms outside those matches are never converted back to text. With the real model/EditorState: construct the confirmed /skill:review atom, place the caret at its start, insert x, then run tokenize. The resulting source is x/skill:review; token_ranges is empty, tokenize returns None, yet the second inline node remains skill. Moving after it and Backspace deletes the complete invocation. A fresh document from the same source has one plain text node. The host scanner also requires a whitespace/start boundary, so submitting the displayed skill does not invoke it. Reconcile existing atoms against the full source grammar, not only newly found token ranges, preserving selection and undo.

* under the License.
*/

import { ComposerInput } from 'maka/host';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Update the existing fixture registries for this new native export

The production and new skill-input fixture registries are updated, but terminal-shell/tests/real_host/components.rs and the fixture in terminal-shell/src/terminal/ui.rs still create maka/host registries containing only host. Importing their existing component fixture now reaches this import and fails before rendering. Current CI42176376971 records the exact maka/host has no export ComposerInput BundleError in CLI jobs127763590415/456/439/405/476/384 and rest-1 jobs127763590423/532. Expose/register the real component plus state class for those existing fixtures and rerun them; a stub declaration alone would only defer the failure to runtime.

Keep source and selection current across composition, paste and application shortcuts. Cover atomic skill editing through behavioral tests and update native editor consumers.

Generated-by: Codex
@M4n5ter
M4n5ter merged commit 5e372db into rust-preview Nov 6, 2026
13 checks passed
@M4n5ter
M4n5ter deleted the fix/skill-books branch November 6, 2026 11:23

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I rechecked the final 40-file change at ac283a3 against the previously reviewed b5e02cb version. I read the complete intervening delta, including the extra fixtures/tests, native editor behavior, key binding fallback, composition and paste handling, and the public UI registry; this supplements the earlier 30-file review.

Both previously reported P2 issues are fixed in the checked paths. model::tokenize now replaces a skill atom whose surrounding source no longer forms a valid token with identical plain source. Using the actual final model and NSH editor-state code, prefixing the atom with x produced plain x/skill:review; a normal backspace then removed one character. The old model control retained the invalid atom. The two current committed model tests pass, alongside six separately identified old-model control tests. All 428 extracted Rust dependency source files and both model versions were checked against their Git blobs; only the isolated workspace manifests were adapted to build the probe. This is an editor-model test, not a complete workbench build. Nine unmodified history tests also pass locally.

The missing native fixture export is addressed by bindings::ui_registry(), which registers ComposerInput and ComposerInputState and is now used by the relevant terminal/pixel/workbench fixture registries. I checked that production registry construction uses the same function. I did not independently execute the native fixture/GPUI suite.

CI remains unresolved. In final-head run 42208071888, the actual checkout is 89c11be (ac283a3 merged into d77b0ff). CLI slices 1/3/6 fail while waiting for enabled Send or persisted drafts, including directory paste, provider failure, workspace trust, attachment-only send and rejected-send preservation. Desktop CLI slice 1 also fails waiting for the expected Unicode draft. I read these job logs. They are current failures, distinct from the earlier missing-export issue; I have not isolated whether each is a production regression or a test/setup problem, so I am not assigning an additional P2 from the timeouts alone or calling CI successful. Some other jobs are still running.

The final head merges without conflicts into fetched rust-preview 42ea54a. The two earlier findings can be closed on the evidence above; complete native input/IME/clipboard and the failing real-Host flows still need acceptance. No protocol/database changes; no approval or merge performed.


Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants