refactor(coding-agent/slash-commands): removed collab qrcode slash commands

- Removed qrcode and qrcode-view subcommands from the collab command.
- Updated showCollabLink to always trigger QR code display.
- Refactored internal verb logic to simplify session sharing flow.
This commit is contained in:
can1357
2026-06-19 01:24:35 +02:00
parent a7fdd0b4ed
commit 8588aa5802
6 changed files with 25 additions and 59 deletions
+3 -5
View File
@@ -20,7 +20,7 @@ Collab session started!
The browser line is click-to-join (an OSC 8 hyperlink to the full `https://` deep link): the relay serves the web guest client at `/`, and the room id + key ride in the URL fragment. From another omp (any directory, any machine), either form works: The browser line is click-to-join (an OSC 8 hyperlink to the full `https://` deep link): the relay serves the web guest client at `/`, and the room id + key ride in the URL fragment. From another omp (any directory, any machine), either form works:
Run `/collab qrcode` to start or re-print hosting with a QR code for the full-control browser link; use `/collab qrcode-view` for a read-only QR code (`/collab qr-view` is a short alias). Running `/collab` or `/collab view` starts or displays the active hosting session, rendering both the terminal/browser join links and their corresponding QR codes.
``` ```
/join my.omp.sh/#mgAYTZwEnpRQtca0CTgn-Q.gdJU… /join my.omp.sh/#mgAYTZwEnpRQtca0CTgn-Q.gdJU…
@@ -32,11 +32,9 @@ The guest's previous session is restored on `/leave` (or when the host stops).
| Command | Effect | | Command | Effect |
|---|---| |---|---|
| `/collab` | Start sharing (or re-print the link when already hosting) | | `/collab` | Start sharing full-control (or re-print the link/QR when already hosting) |
| `/collab <relay>` | Start sharing through a specific relay (`relay.example.com`, `ws://localhost:7475`) | | `/collab <relay>` | Start sharing through a specific relay (`relay.example.com`, `ws://localhost:7475`) |
| `/collab view` | Print a read-only (view-only) link (starts sharing first if needed) | | `/collab view` | Start sharing read-only (or re-print the link/QR when already hosting) |
| `/collab qrcode` | Print a QR code for a full-control browser link (starts sharing first if needed) |
| `/collab qrcode-view` | Print a QR code for a read-only browser link (starts sharing first if needed); `/collab qr-view` is an alias |
| `/collab status` | Show link + participants | | `/collab status` | Show link + participants |
| `/collab stop` | Stop sharing | | `/collab stop` | Stop sharing |
| `/join <link>` | Join a shared session as a guest | | `/join <link>` | Join a shared session as a guest |
+8 -8
View File
@@ -164,26 +164,26 @@ describe("kimi think tags (<think>…</think>)", () => {
}); });
}); });
describe("pi native thinking channel (<thinking>…</thinking>)", () => { describe("pi native thinking channel (¤…¤)", () => {
it("routes <thinking> to thinking, keeping it out of the reply and calls", () => { it("routes ¤ to thinking, keeping it out of the reply and calls", () => {
const events = scan("pi", "<thinking>reasoning</thinking><call:foo x=1/>"); const events = scan("pi", "¤reasoning¤§foo x=1\n");
expect(thinkingText(events)).toBe("reasoning"); expect(thinkingText(events)).toBe("reasoning");
expect(callNames(events)).toEqual([{ name: "foo", arguments: { x: 1 } }]); expect(callNames(events)).toEqual([{ name: "foo", arguments: { x: 1 } }]);
expect(visibleText(events)).not.toContain("<thinking>"); expect(visibleText(events)).not.toContain("¤");
}); });
it("round-trips renderThinking through the scanner", () => { it("round-trips renderThinking through the scanner", () => {
const rendered = getDialectDefinition("pi").renderThinking("reasoning"); const rendered = getDialectDefinition("pi").renderThinking("reasoning");
expect(rendered).toBe("<thinking>\nreasoning\n</thinking>"); expect(rendered).toBe("¤\nreasoning\n¤");
const events = scan("pi", `${rendered}visible`); const events = scan("pi", `${rendered}visible`);
expect(thinkingText(events).trim()).toBe("reasoning"); expect(thinkingText(events).trim()).toBe("reasoning");
expect(visibleText(events)).toBe("visible"); expect(visibleText(events)).toBe("visible");
}); });
it("treats <thinking> as plain text when parseThinking is disabled", () => { it("treats ¤ as plain text when parseThinking is disabled", () => {
const events = scan("pi", "<thinking>x</thinking>answer", { options: { parseThinking: false } }); const events = scan("pi", "¤x¤answer", { options: { parseThinking: false } });
expect(thinkingBoundaries(events)).toBe(0); expect(thinkingBoundaries(events)).toBe(0);
expect(visibleText(events)).toContain("<thinking>x</thinking>"); expect(visibleText(events)).toContain("¤x¤");
}); });
}); });
+1 -3
View File
@@ -50,9 +50,7 @@ describe("renderToolExamples", () => {
}; };
const rendered = renderToolExamples(tool, "pi"); const rendered = renderToolExamples(tool, "pi");
expect(rendered).toContain("<call:find>"); expect(rendered).toContain('§find paths=["src/**/*.ts"]');
expect(rendered).toContain("<paths>");
expect(rendered).toContain("src/**/*.ts");
}); });
it("renders call example in hermes format", () => { it("renders call example in hermes format", () => {
+1 -1
View File
@@ -5,7 +5,7 @@
### Added ### Added
- Updated the `pi` option of the `tools.format` setting to use the new compact sigil-delimited owned tool-calling dialect (`§`/`«…»`/`¤`/`‡‡`) that uses ~46% fewer tokens than the legacy format on typical calls. - Updated the `pi` option of the `tools.format` setting to use the new compact sigil-delimited owned tool-calling dialect (`§`/`«…»`/`¤`/`‡‡`) that uses ~46% fewer tokens than the legacy format on typical calls.
- Added `/collab qrcode` and `/collab qrcode-view` one-shot terminal QR output for browser join links and a `collab.webUrl` setting for separately hosted collab web clients. - Integrated terminal QR codes directly into `/collab` and `/collab view` to display both deep links and scannable codes, and added a `collab.webUrl` setting for separately hosted collab web clients.
### Changed ### Changed
@@ -108,15 +108,9 @@ function showCollabQrCode(ctx: InteractiveModeContext, webLink: string): void {
} }
} }
function showCollabLink( function showCollabLink(ctx: InteractiveModeContext, host: CollabHost, heading: string, view = false): void {
ctx: InteractiveModeContext,
host: CollabHost,
heading: string,
view = false,
options?: { forceQr?: boolean },
): void {
ctx.showStatus(collabLinkHint(host, heading, view), { dim: false }); ctx.showStatus(collabLinkHint(host, heading, view), { dim: false });
if (options?.forceQr) showCollabQrCode(ctx, view ? host.webViewLink : host.webLink); showCollabQrCode(ctx, view ? host.webViewLink : host.webLink);
} }
function formatFreshSessionResult(result: FreshSessionResult): string { function formatFreshSessionResult(result: FreshSessionResult): string {
@@ -598,13 +592,11 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
{ {
name: "collab", name: "collab",
description: "Share this session live via a relay", description: "Share this session live via a relay",
inlineHint: "[start|view|stop|status|qrcode|qrcode-view] [relayUrl]", inlineHint: "[start|view|stop|status] [relayUrl]",
subcommands: [ subcommands: [
{ name: "view", description: "Share a read-only link (guests can watch, not prompt)" }, { name: "view", description: "Share a read-only link (guests can watch, not prompt)" },
{ name: "status", description: "Show link + participants" }, { name: "status", description: "Show link + participants" },
{ name: "stop", description: "Stop sharing" }, { name: "stop", description: "Stop sharing" },
{ name: "qrcode", description: "Print a QR code for a full-control browser link" },
{ name: "qrcode-view", description: "Print a QR code for a read-only browser link" },
], ],
allowArgs: true, allowArgs: true,
handleTui: async (command, runtime) => { handleTui: async (command, runtime) => {
@@ -642,23 +634,14 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
ctx.showError("Already in a collab session as a guest (/leave first)"); ctx.showError("Already in a collab session as a guest (/leave first)");
return; return;
} }
const knownStartVerb = const knownStartVerb = verb === "start" || verb === "view";
verb === "start" || verb === "view" || verb === "qrcode" || verb === "qrcode-view" || verb === "qr-view"; const view = verb === "view";
const view = verb === "view" || verb === "qrcode-view" || verb === "qr-view";
const forceQr = verb === "qrcode" || verb === "qrcode-view" || verb === "qr-view";
if (ctx.collabHost) { if (ctx.collabHost) {
showCollabLink( showCollabLink(
ctx, ctx,
ctx.collabHost, ctx.collabHost,
forceQr view ? "Read-only collab session active" : "Collab session active",
? view
? "Read-only collab QR code"
: "Collab QR code"
: view
? "Read-only collab link"
: "Collab session active",
view, view,
{ forceQr },
); );
return; return;
} }
@@ -681,7 +664,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
return; return;
} }
ctx.collabHost = host; ctx.collabHost = host;
showCollabLink(ctx, host, "Collab session started!", view, { forceQr }); showCollabLink(ctx, host, "Collab session started!", view);
}, },
}, },
{ {
@@ -78,12 +78,12 @@ function mockStartedHostLinks() {
}); });
} }
describe("/collab qrcode slash command", () => { describe("/collab slash command QR code rendering", () => {
it("starts hosting and prints a one-shot full-control QR", async () => { it("starts hosting and prints a one-shot full-control QR", async () => {
const startSpy = mockStartedHostLinks(); const startSpy = mockStartedHostLinks();
const harness = createRuntimeHarness(); const harness = createRuntimeHarness();
const handled = await executeBuiltinSlashCommand("/collab qrcode", harness.runtime); const handled = await executeBuiltinSlashCommand("/collab", harness.runtime);
expect(handled).toBe(true); expect(handled).toBe(true);
expect(harness.setText).toHaveBeenCalledWith(""); expect(harness.setText).toHaveBeenCalledWith("");
@@ -103,7 +103,7 @@ describe("/collab qrcode slash command", () => {
const startSpy = mockStartedHostLinks(); const startSpy = mockStartedHostLinks();
const harness = createRuntimeHarness(); const harness = createRuntimeHarness();
const handled = await executeBuiltinSlashCommand("/collab qrcode-view", harness.runtime); const handled = await executeBuiltinSlashCommand("/collab view", harness.runtime);
expect(handled).toBe(true); expect(handled).toBe(true);
expect(startSpy).toHaveBeenCalledWith("wss://relay.example.com", ""); expect(startSpy).toHaveBeenCalledWith("wss://relay.example.com", "");
@@ -121,7 +121,7 @@ describe("/collab qrcode slash command", () => {
it("prints the active full-control browser QR when hosting", async () => { it("prints the active full-control browser QR when hosting", async () => {
const harness = createRuntimeHarness({ collabHost: fakeHost() }); const harness = createRuntimeHarness({ collabHost: fakeHost() });
const handled = await executeBuiltinSlashCommand("/collab qrcode", harness.runtime); const handled = await executeBuiltinSlashCommand("/collab", harness.runtime);
expect(handled).toBe(true); expect(handled).toBe(true);
const statusText = harness.showStatus.mock.calls[0]?.[0] as string; const statusText = harness.showStatus.mock.calls[0]?.[0] as string;
@@ -138,7 +138,7 @@ describe("/collab qrcode slash command", () => {
const webViewLink = "https://my.omp.sh/#read-only"; const webViewLink = "https://my.omp.sh/#read-only";
const harness = createRuntimeHarness({ collabHost: fakeHost({ webLink, webViewLink }) }); const harness = createRuntimeHarness({ collabHost: fakeHost({ webLink, webViewLink }) });
const handled = await executeBuiltinSlashCommand("/collab qrcode-view", harness.runtime); const handled = await executeBuiltinSlashCommand("/collab view", harness.runtime);
expect(handled).toBe(true); expect(handled).toBe(true);
const statusText = harness.showStatus.mock.calls[0]?.[0] as string; const statusText = harness.showStatus.mock.calls[0]?.[0] as string;
@@ -151,17 +151,4 @@ describe("/collab qrcode slash command", () => {
expect(component.url).toBe(webViewLink); expect(component.url).toBe(webViewLink);
expect(component.render(10).join("\n")).toContain("QR code hidden"); expect(component.render(10).join("\n")).toContain("QR code hidden");
}); });
it("accepts qr-view as an alias for qrcode-view", async () => {
const webLink = "https://my.omp.sh/#full-control";
const webViewLink = "https://my.omp.sh/#read-only";
const harness = createRuntimeHarness({ collabHost: fakeHost({ webLink, webViewLink }) });
const handled = await executeBuiltinSlashCommand("/collab qr-view", harness.runtime);
expect(handled).toBe(true);
const presented = harness.present.mock.calls[0]?.[0] as readonly unknown[];
expect(presented[1]).toBeInstanceOf(CollabQrCodeComponent);
expect((presented[1] as CollabQrCodeComponent).url).toBe(webViewLink);
});
}); });