mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(coding-agent): simplify session sharing links
This commit is contained in:
parent
77f2d1235e
commit
f4585b8bec
3 changed files with 34 additions and 47 deletions
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
- Added transcript usage notices for compaction and branch summaries when cache miss notices are enabled.
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed session sharing to render clickable terminal links and Radius shares to display only the artifact's canonical URL.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed UTF-8 BOM markers preventing frontmatter and user configuration files from loading ([#8337](https://github.com/earendil-works/pi/issues/8337)).
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ export function expandTildePath(path: string): string {
|
|||
|
||||
const DEFAULT_SHARE_VIEWER_URL = "https://pi.dev/session/";
|
||||
|
||||
/** Get the share viewer URL for a gist ID or Radius artifact reference. */
|
||||
/** Get the share viewer URL for a gist ID. */
|
||||
export function getShareViewerUrl(gistId: string): string {
|
||||
const baseUrl = process.env.PI_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
|
||||
return `${baseUrl}#${gistId}`;
|
||||
|
|
|
|||
|
|
@ -6085,7 +6085,7 @@ export class InteractiveMode {
|
|||
private async handleShareCommand(): Promise<void> {
|
||||
// Radius artifacts natively support JSONL sessions. Gist fallback keeps the legacy HTML upload.
|
||||
const jsonlFile = path.join(os.tmpdir(), "session.jsonl");
|
||||
const htmlFile = path.join(os.tmpdir(), "session.html");
|
||||
let htmlFile = null;
|
||||
|
||||
try {
|
||||
try {
|
||||
|
|
@ -6094,10 +6094,21 @@ export class InteractiveMode {
|
|||
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
return;
|
||||
}
|
||||
const radiusResult = await this.tryShareViaRadius(jsonlFile);
|
||||
if (radiusResult !== "radius-unavailable") return;
|
||||
if (await this.tryShareViaRadius(jsonlFile)) return;
|
||||
|
||||
try {
|
||||
const authResult = spawnSync("gh", ["auth", "status"], { encoding: "utf-8" });
|
||||
if (authResult.status !== 0) {
|
||||
this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
htmlFile = path.join(os.tmpdir(), "session.html");
|
||||
await this.session.exportToHtml(htmlFile, { themeName: theme.name });
|
||||
} catch (error: unknown) {
|
||||
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||
|
|
@ -6107,7 +6118,9 @@ export class InteractiveMode {
|
|||
} finally {
|
||||
for (const tmpFile of [jsonlFile, htmlFile]) {
|
||||
try {
|
||||
fs.unlinkSync(tmpFile);
|
||||
if (tmpFile !== null) {
|
||||
fs.unlinkSync(tmpFile);
|
||||
}
|
||||
} catch {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
|
|
@ -6115,16 +6128,16 @@ export class InteractiveMode {
|
|||
}
|
||||
}
|
||||
|
||||
private async tryShareViaRadius(tmpFile: string): Promise<"shared" | "radius-unavailable"> {
|
||||
private async tryShareViaRadius(tmpFile: string): Promise<boolean> {
|
||||
const provider = this.session.modelRuntime.getProvider("radius");
|
||||
if (!provider) return "radius-unavailable";
|
||||
if (!provider) return false;
|
||||
|
||||
const gatewayUrl = DEFAULT_RADIUS_GATEWAY;
|
||||
|
||||
const token = getAuthCredential(
|
||||
await this.session.modelRuntime.getAuth("radius", { minOAuthValidityMs: 5 * 60_000 }),
|
||||
);
|
||||
if (!token) return "radius-unavailable";
|
||||
if (!token) return false;
|
||||
|
||||
const loader = new BorderedLoader(this.ui, theme, "Uploading to Radius...");
|
||||
this.editorContainer.clear();
|
||||
|
|
@ -6151,30 +6164,22 @@ export class InteractiveMode {
|
|||
body,
|
||||
signal: loader.signal,
|
||||
});
|
||||
if (loader.signal.aborted) return "shared";
|
||||
if (loader.signal.aborted) return true;
|
||||
const json = (await response.json().catch(() => null)) as {
|
||||
artifact?: { canonical_url?: string; url?: string; visibility?: string };
|
||||
artifact?: { canonical_url: string };
|
||||
error?: string;
|
||||
} | null;
|
||||
if (loader.signal.aborted) return "shared";
|
||||
if (loader.signal.aborted) return true;
|
||||
this.restoreShareEditor(loader);
|
||||
if (!response.ok || !json?.artifact) {
|
||||
this.showError(
|
||||
`Failed to upload Radius artifact: ${json?.error || response.statusText || response.status}`,
|
||||
);
|
||||
return "shared";
|
||||
return true;
|
||||
}
|
||||
const shareUrl = json.artifact.canonical_url || json.artifact.url;
|
||||
if (!shareUrl) {
|
||||
this.showError("Failed to upload Radius artifact: response did not include a share URL");
|
||||
return "shared";
|
||||
}
|
||||
const artifactId = this.radiusArtifactIdFromUrl(shareUrl);
|
||||
const previewUrl =
|
||||
json.artifact.visibility === "public" && artifactId ? getShareViewerUrl(`radius/${artifactId}`) : shareUrl;
|
||||
const visibilityNote = json.artifact.visibility === "public" ? "" : " (private; sign-in required)";
|
||||
this.showStatus(`Share URL: ${previewUrl}${visibilityNote}\nRadius artifact: ${shareUrl}`);
|
||||
return "shared";
|
||||
const shareUrl = json.artifact.canonical_url;
|
||||
this.showStatus(`Share URL: ${hyperlink(shareUrl, shareUrl)}`);
|
||||
return true;
|
||||
} catch (error: unknown) {
|
||||
if (!loader.signal.aborted) {
|
||||
this.restoreShareEditor(loader);
|
||||
|
|
@ -6182,23 +6187,11 @@ export class InteractiveMode {
|
|||
`Failed to upload Radius artifact: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||
);
|
||||
}
|
||||
return "shared";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private async shareViaGist(tmpFile: string): Promise<void> {
|
||||
// Check if gh is available and logged in
|
||||
try {
|
||||
const authResult = spawnSync("gh", ["auth", "status"], { encoding: "utf-8" });
|
||||
if (authResult.status !== 0) {
|
||||
this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show cancellable loader, replacing the editor
|
||||
const loader = new BorderedLoader(this.ui, theme, "Creating gist...");
|
||||
this.editorContainer.clear();
|
||||
|
|
@ -6250,7 +6243,7 @@ export class InteractiveMode {
|
|||
|
||||
// Create the preview URL
|
||||
const previewUrl = getShareViewerUrl(gistId);
|
||||
this.showStatus(`Share URL: ${previewUrl}\nGist: ${gistUrl}`);
|
||||
this.showStatus(`Share URL: ${hyperlink(previewUrl, previewUrl)}\nGist: ${hyperlink(gistUrl, gistUrl)}`);
|
||||
} catch (error: unknown) {
|
||||
if (!loader.signal.aborted) {
|
||||
this.restoreShareEditor(loader);
|
||||
|
|
@ -6266,16 +6259,6 @@ export class InteractiveMode {
|
|||
this.ui.setFocus(this.editor);
|
||||
}
|
||||
|
||||
private radiusArtifactIdFromUrl(value: string): string | null {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
const match = /^\/artifact\/([^/?#]+)\/?$/iu.exec(url.pathname);
|
||||
return match ? match[1] : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async handleCopyCommand(options: { flashConfirmation?: boolean } = {}): Promise<void> {
|
||||
const text = this.session.getLastAssistantText();
|
||||
if (!text) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue