feat(#2102): make pi a first-class installable runtime + fix its dispatch (ADR-1239)
Net-new EoS/pi installable runtime — purely additive (no prior runtime==='pi'
branches). pi is a bun-runtime programmatic-CLI whose /gsd command is registered
by a native ExtensionAPI extension and dispatches through the embedded engine.
Stage 1 (install plumbing):
- capabilities/pi/capability.json: full hostIntegration descriptor (imperative /
slash-programmatic / active-model / native-extension / bun) + hostBehaviors
{nativePlugin, pluginOnlyInstall}.
- --pi flag + interactive-menu renumber (All 17->18); pi added to RUNTIME_FLAG_IDS,
RUNTIME_LABELS, RUNTIME_META, allRuntimes/runtimeMap, model-catalog defaults.
- Install mirrors OpenCode: pi installs the gsd.cjs extension + the shared engine
payload (gsd-core + scripts + config markers) + the shared hooks bundle (spawned
by the extension at lifecycle events, like OpenCode's plugin). pluginOnlyInstall
EXCLUDES declarative command/agent/skill markdown, which pi has no host-read
surface for (its /gsd is programmatic). _installNativePluginIfDeclared (extracted
from the opencode-family path) copies pi/gsd.cjs -> ~/.pi/agent/extensions/gsd.cjs
(global) / .pi/extensions/ (local). pi added to package.json files.
- Golden: new pi.json (320 files: extension + engine + 27-file hooks bundle, no
markdown); the 16 other fixtures + claude-local change only by the shared
model-catalog hash line.
Stage 2 (real dispatch + upgrades):
- Shared dispatchGsdCommand() (shell-command-projection): bounded, no-throw
subprocess-shim to gsd-tools.cjs (the only full-surface dispatch path; no
in-process full-hub factory exists). Fixes pi/gsd.cjs's createHub()-no-args bug
(every dispatch was UnknownCommand) AND the identical bug in mcp-server.cts's
gsd_invoke_command, which a vacuous unknown-family-only test had masked (now has
a real dispatch regression test).
- pi/gsd.cjs: /gsd handler now (args, ctx) - tokenizes (quote-aware, via the
shipped hooks/lib/git-cmd.js) + dispatches real family/subcommand (not hardcoded
query/help); gsd_invoke gets a TypeBox (JSON-schema-fallback) parameters schema +
consumes params; getArgumentCompletions; before_provider_request active-model
steering (fail-open on null resolution); functional session_start /
before_agent_start / session_before_compact hook bridges (spawn the shipped GSD
hook scripts).
- EXTENSION_EVENT_SURFACES.pi expanded from ['tool_call'] to the full 30-event
vocabulary.
Docs (host-integration matrix + how-to) + changeset (Added).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
28
tests/fixtures/pi-host-plugin.cjs
vendored
28
tests/fixtures/pi-host-plugin.cjs
vendored
@@ -14,10 +14,18 @@
|
||||
* behaviorally testable without a live pi runtime. The default export matches
|
||||
* pi's extension entry shape: `export default function (pi: ExtensionAPI) { … }`.
|
||||
*
|
||||
* #2102 Stage 2: registerCommand takes `handler(args, ctx)` (args is the raw
|
||||
* string after the command) — NOT `execute(ctx)`, which the original #1682
|
||||
* cut used. gsd_invoke's `execute` takes pi's real 5-arg tool-execute
|
||||
* signature `(toolCallId, params, signal, onUpdate, ctx)`. See pi/gsd.cjs for
|
||||
* the full production binding this reference fixture mirrors.
|
||||
*
|
||||
* NOTE: this is the reference binding that proves the ExtensionAPI imperative
|
||||
* adapter (#1682 AC). Full `--pi` installable-runtime integration (descriptor +
|
||||
* installer wiring + golden parity 16→17) is a larger follow-up tracked
|
||||
* separately — it is intentionally NOT added to the runtime registry here.
|
||||
* adapter (#1682 AC), kept as a mock-friendly fixture independent of the real
|
||||
* `pi/gsd.cjs` extension. Full `--pi` installable-runtime integration
|
||||
* (descriptor + installer wiring + golden parity 16→17) shipped in #2102
|
||||
* Stage 1 — see capabilities/pi/capability.json and
|
||||
* tests/fixtures/golden-install-parity/pi.json.
|
||||
*
|
||||
* @param {object} pi pi ExtensionAPI (registerTool/registerCommand/on/…)
|
||||
*/
|
||||
@@ -30,9 +38,12 @@ module.exports = function gsdPiPlugin(pi) {
|
||||
// imperative adapter (createImperativeAdapter({runtime:'pi'}) + dispatch).
|
||||
pi.registerCommand('gsd', {
|
||||
description: 'Invoke a GSD command via the embedded engine (imperative adapter).',
|
||||
execute: async function /* ctx */ () {
|
||||
handler: async function (args, ctx) {
|
||||
void args;
|
||||
void ctx;
|
||||
// Engine dispatch is wired by the host at load (createImperativeAdapter).
|
||||
// Kept declarative in the reference; the real binding dispatches the hub.
|
||||
// Kept declarative in the reference; the real binding (pi/gsd.cjs)
|
||||
// dispatches through gsd-tools.cjs via dispatchGsdCommand.
|
||||
},
|
||||
});
|
||||
|
||||
@@ -41,7 +52,12 @@ module.exports = function gsdPiPlugin(pi) {
|
||||
pi.registerTool({
|
||||
name: 'gsd_invoke',
|
||||
description: 'Invoke a GSD command family/subcommand through the engine.',
|
||||
execute: async function () {
|
||||
execute: async function (toolCallId, params, signal, onUpdate, ctx) {
|
||||
void toolCallId;
|
||||
void params;
|
||||
void signal;
|
||||
void onUpdate;
|
||||
void ctx;
|
||||
return 'ok';
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user