CmdPal JS/TS Extensions - Phase 6: docs + parity sample extension - #49329
Open
michaeljolley wants to merge 21 commits into
Open
CmdPal JS/TS Extensions - Phase 6: docs + parity sample extension#49329michaeljolley wants to merge 21 commits into
michaeljolley wants to merge 21 commits into
Conversation
Adds the JSON-RPC design spec into the repo, a buildable TypeScript parity sample that mirrors the C# SamplePagesExtension, and reconciles the gallery install layout so an npm-installed extension is actually discovered. Docs (src/modules/cmdpal/doc/json-rpc-spec): overview plus 01-architecture, 02-typescript-sdk, 03-jsonrpc-protocol, 04-manifest-packaging, and a rewritten 05-getting-started. Corrected class/method-name and API drift against the shipped Phases 1-5 code, fixed the overview date, and removed all long dashes. Sample (src/modules/cmdpal/ext/SampleJSExtension): source-only project that builds against the local SDK via a relative file dependency; dist and node_modules are git-ignored. Layout reconciliation: JsExtensionPackageLayout.Materialize hoists the package npm installs under node_modules up to the JSExtensions/<name> root that discovery scans, with unit tests covering the installed layout. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 9a289c8c-5264-482e-a363-5b4593cf9c73
…ry' into dev/mjolley/phase-6-cmdpal-docs-sample
Bound the live-updating sample pages' refresh timers to page visibility and reconcile the packaging doc's SDK dependency example. - Add LiveRefresh helper that arms a single timer while a page is being observed and stops it once the host stops re-fetching (navigate away), restarting on navigate back. Replaces the permanent setInterval in liveDetailsPage and updatingItemsPage. - Cache the two timer-owning pages as singletons in SamplesListPage so repeated navigation cannot churn page instances or accumulate timers. - 04-manifest-packaging.md: reference @microsoft/cmdpal-sdk via a relative file: dependency and note that a semver range applies once it is published, matching the unpublished-package reality stated elsewhere in the doc. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 9a289c8c-5264-482e-a363-5b4593cf9c73
…ontext, separators, status) Applies five sample-authoring fixes to SampleJSExtension now that the SDK and host fixes are merged up to phase 6: - Sections: emit visible headings with titled Separator entries between groups instead of tagging command items with a section field the host ignores. - Hero image: ship a local assets/hero.png and reference it by an absolute path resolved from import.meta.url, so the details hero renders without a network connection. The build copies assets into dist/assets. - Nested context menu: demonstrate a genuine two-level moreCommands submenu on a context item now that nested context menus are supported end to end. - Details separator: use an empty-key separator where a divider line is intended so the horizontal rule renders instead of a bold heading. - Details command buttons: wire the buttons to a visible indeterminate status that resolves to a success message, exercising the merged status fixes. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 2ccc215f-7518-4f6f-92a4-1cfd112fb01f
Align the documented JS extensions install location in the JSON-RPC spec and the sample extension README with the CmdPal data folder path segment change from CommandPalette to CmdPal. Co-authored-by: Copilot App <[email protected]> Copilot-Session: f69b1dcf-ed86-4e74-8373-b8414e1ac961
…bilities Follow the manifest changes through the JS/TS extension docs and sample: - 04-manifest-packaging.md: add the top-level npm "author" field to the reference, note that cmdpal.publisher falls back to the author name, and remove the inert cmdpal.capabilities field from the field list, the tables, and the JSON examples. - 05-getting-started.md: drop cmdpal.capabilities from the walkthrough example. - SampleJSExtension/package.json: remove the cmdpal.capabilities array. The runtime initialize-handshake capabilities documented in 03-jsonrpc-protocol.md and the prose in the sample README and samplesListPage.ts about C# features not yet mirrored are unrelated and left untouched. Co-authored-by: Copilot App <[email protected]> Copilot-Session: de2fe464-6835-4cd9-9c6b-0ac9351cdb99
Co-authored-by: Copilot App <[email protected]> Copilot-Session: 762976e0-2453-40ca-8034-978a04a19d1e
Co-authored-by: Copilot App <[email protected]> Copilot-Session: 3f0875f9-177f-40db-888c-248a044d2bb9
Co-authored-by: Copilot App <[email protected]> Copilot-Session: 9470f549-1997-44de-b0a6-1ce4562a51f0
… phase-6-cmdpal-docs-sample
…sample Propagate the phase-5 fail-closed npm install transaction up into the docs and sample phase. The only code conflict was in NpmCommandRunner, where phase-6 had wired the runner success path to JsExtensionPackageLayout.Materialize. Phase-5 moves that hoisting into the installer staging step (AssembleDiscoveryLayout) as part of the staging-and-atomic-promote transaction, so the runner now returns the resolved integrity and no longer materializes in place. Phase-6's JsExtensionPackageLayout helper, its tests, and the json-rpc-spec docs are kept intact. Added a parameterless NpmCommandResult.Ok() overload so that helper keeps compiling against the phase-5 result shape. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 234c59f1-a32b-4c98-97bb-ab50a4d07fd9
Address the phase 6 punchlist for the Command Palette JS/TS extensions
feature (docs plus sample extension), staying within CommandPalette.slnf.
- Gallery schema doc (04-manifest-packaging.md) now shows the real gallery
model (id, title, author, installSources with the jsonrpc npm source
inside installSources) and documents the required exact version, sha512
integrity, and optional HTTPS-allowlist registry fields. A parser test
feeds the exact documentation JSON through the production gallery parser.
- Reconcile package hoisting onto a single identity-aware path:
JsExtensionPackageLayout resolves the requested package identity (scoped
and unscoped), enforces containment, and rejects ambiguous layouts. The
installer calls this one helper.
- Manifest relative icon paths resolve against the manifest directory with
package containment enforced (reject parent-directory escapes and
reparse points). Adds installed-package icon tests.
- Sample nested forms carry stable form IDs for recursive routing; status
commands hide the working status before showing completion using stable
status handles.
- Document Separator("Title") as the supported grouping mechanism.
- Production packaging guidance no longer tells authors to depend on the
repo-local SDK; it states registry distribution is not yet supported and
adds a packed-SDK smoke test (scripts/verify-pack.mjs, verify:pack) that
installs a tarball into a clean project and type-checks against it. The
script falls back to a deterministic tarball when npm pack is unavailable.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 3158d6a3-1d4d-4772-882a-91ede0cc7f9b
Propagates the stale-test and golden-fixture corrections so the SDK typecheck stays green at this layer, including the phase-6 forms tests. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 311db8aa-f8db-47bb-943f-5447037946c7
The re-serialize form identity test destructured sent from createHarness but never referenced it, tripping eslint no-unused-vars and turning npm run check red at this layer. Drop the unused binding so the lint gate passes; the test still asserts on submit and replies. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 311db8aa-f8db-47bb-943f-5447037946c7
r2-p6-01: AssembleDiscoveryLayout treated a hoisted node_modules/@scope directory as a leaf package, so when the destination scope already existed (for example a version-pinned scoped dependency the package bundled) the whole incoming @scope was skipped, silently dropping sibling scoped packages. Merge scoped dependencies one package at a time so every @scope/pkg is preserved. Adds a unit test covering mixed unscoped and multiple @scope/pkg entries. r2-p6-02: reconcile the SDK installation guide with getting-started. The SDK is not published to npm, so document repo-relative file: consumption and build steps instead of an unpublished npm version. r2-p6-03: correct the docs to state that nested context menus are supported; ContextItem carries its own moreCommands and the SDK serializes nesting recursively. r2-p6-04: remove the section field from the command-bearing item example and clarify that the host ignores section on interactive items. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 311db8aa-f8db-47bb-943f-5447037946c7
Bring the phase-5 gallery installer round-2 fixes down onto phase-6. Resolved NpmJsExtensionInstaller.cs: kept phase-5 RollbackPromotedInstall plus junction-root guard and threaded uninstall token, while keeping phase-6 extraction of layout helpers into JsExtensionPackageLayout. Co-authored-by: Copilot App <[email protected]> Copilot-Session: 311db8aa-f8db-47bb-943f-5447037946c7
michaeljolley
force-pushed
the
dev/mjolley/phase-5-cmdpal-gallery
branch
from
July 27, 2026 21:14
8d8c090 to
a20c022
Compare
michaeljolley
force-pushed
the
dev/mjolley/phase-6-cmdpal-docs-sample
branch
from
July 27, 2026 21:14
efdf0b5 to
d76e2b0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 6 (final) of adding JavaScript/TypeScript extensions to Command Palette. This PR is atomic to Phase 6 and stacks on Phase 5 (PR #49326); its base branch is
dev/mjolley/phase-5-cmdpal-gallery, notmain. Related issue: #48707.It stays a draft until reviewed.
Phase 6 delivers three things:
A. Design spec docs (
src/modules/cmdpal/doc/json-rpc-spec)Brings the JSON-RPC design spec into the repo:
overview.mdplus01-architecture,02-typescript-sdk,03-jsonrpc-protocol,04-manifest-packaging, and05-getting-started. The drafts were reviewed against what actually shipped in Phases 1-5 and corrected:JSCommandItemAdapter,JSInvokableCommandAdapter,JSModelMapper,JSCmdPalSection), replacing names that never shipped.CommandResultwire serialization (string-union kind serialized to the numericKind/Argsshape) documented accurately.05-getting-startedwas fully rewritten to the real API (CommandProviderBase/InvokableCommandBase/ListPageBase/DynamicListPageBase/ContentPageBase,run(() => new Provider()), string-union results,ExtensionHost.log), Node 22, SDK 0.1.0, ESM / NodeNext.04-manifest-packaginginstall flow updated to describe the materialize/hoist step (see C below).Last updateddate inoverview.mdand removed every long dash across all six files.B. Parity sample (
src/modules/cmdpal/ext/SampleJSExtension)A source-only TypeScript sample that mirrors the C#
SamplePagesExtensionview-for-view using@microsoft/cmdpal-sdk(referenced via a relativefile:dependency, so it builds without publishing).npm ci && npm run buildsucceeds;dist/andnode_modules/are git-ignored. The README explains how to sideload it into theJSExtensionsdirectory. It was smoke-tested over stdio:initialize, top-level command, the 23-item samples index, a nested list page, and markdown content all respond correctly.Capabilities intentionally not mirrored (JS protocol does not expose them; no protocol methods were invented):
SampleDockBand/SampleButtonsDockBand):GetDockBandsis not exposed.IParameterRunis not exposed.DataPackagein the data transfer sample: clipboard copy is mirrored; drag-drop is not exposed.IToastArgs2), andDetailssize (Small/Medium/Large): not in the JSToastArgs/Detailsshapes.EvilSamplesPageand issue-specific host-ABI repros: reproduce in-process C# ABI edge cases, not applicable to isolated JS extensions.Approximated (capability exists but differs):
DynamicListPageBase+notifyItemsChangedon an interval, since JSDetailshas no observable push.getItemscall.textToSuggest.ContextItemhas nomoreCommands).C. Install-layout reconciliation
Phase 5 flagged that
npm install <pkg>lands the package underJSExtensions/<name>/node_modules/<pkg>/package.json, while Phase 4 discovery scansJSExtensions/<name>/package.json. Fixed with the least invasive option: after npm exits successfully,NpmCommandRunnercallsJsExtensionPackageLayout.Materialize(targetDirectory), which finds the installed package whosepackage.jsoncarries a validcmdpalsection and hoists it (including mergingnode_modules) up to theJSExtensions/<name>root that discovery expects. This matches the spec doc 04 layout. Covered byJsExtensionPackageLayoutTests.Validation
SortByAuthorCommand_SortsEntriesByAuthorflake passes on re-run). No C# changed since.npm ci && npm run buildexit 0; stdio smoke test passed.