From 57dd8f8c25baa4dc7b43c024f0c33fb7fdc4a761 Mon Sep 17 00:00:00 2001 From: Evgeny Shurakov Date: Thu, 12 Mar 2026 13:54:34 +0100 Subject: [PATCH] fix(cli): restore Kilo share URL support in import command The upstream merge (v1.1.54) overwrote Kilo-specific URL handling with the opencode ShareNext flow, breaking import for app.kilo.ai/s/ URLs. Restore parsing of https://app.kilo.ai/s/ and fetching from ingest.kilosessions.ai instead of the opncd.ai share API. --- packages/opencode/src/cli/cmd/import.ts | 22 +++++++++++----------- packages/opencode/test/cli/import.test.ts | 17 ++++++++++------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/opencode/src/cli/cmd/import.ts b/packages/opencode/src/cli/cmd/import.ts index c905d3b0c62..9c4b36a3838 100644 --- a/packages/opencode/src/cli/cmd/import.ts +++ b/packages/opencode/src/cli/cmd/import.ts @@ -6,7 +6,6 @@ import { bootstrap } from "../bootstrap" import { Database } from "../../storage/db" import { SessionTable, MessageTable, PartTable } from "../../session/session.sql" import { Instance } from "../../project/instance" -import { ShareNext } from "../../share/share-next" import { EOL } from "os" import { Filesystem } from "../../util/filesystem" import { Log } from "../../util/log" @@ -21,11 +20,13 @@ export type ShareData = | { type: "session_diff"; data: unknown } | { type: "model"; data: unknown } -/** Extract share ID from a share URL like https://opncd.ai/share/abc123 */ +// kilocode_change start +/** Extract share ID from a Kilo share URL like https://app.kilo.ai/s/abc123 */ export function parseShareUrl(url: string): string | null { - const match = url.match(/^https?:\/\/[^/]+\/share\/([a-zA-Z0-9_-]+)$/) + const match = url.match(/^https?:\/\/app\.kilo\.ai\/s\/([a-zA-Z0-9_-]+)$/) return match ? match[1] : null } +// kilocode_change end /** * Transform ShareNext API response (flat array) into the nested structure for local file storage. @@ -130,16 +131,15 @@ export const ImportCommand = cmd({ const isUrl = args.file.startsWith("http://") || args.file.startsWith("https://") if (isUrl) { + // kilocode_change start const slug = parseShareUrl(args.file) if (!slug) { - const baseUrl = await ShareNext.url() - process.stdout.write(`Invalid URL format. Expected: ${baseUrl}/share/`) + process.stdout.write(`Invalid URL format. Expected: https://app.kilo.ai/s/`) process.stdout.write(EOL) return } - const baseUrl = await ShareNext.url() - const response = await fetch(`${baseUrl}/api/share/${slug}/data`) + const response = await fetch(`https://ingest.kilosessions.ai/session/${encodeURIComponent(slug)}`) if (!response.ok) { process.stdout.write(`Failed to fetch share data: ${response.statusText}`) @@ -147,16 +147,16 @@ export const ImportCommand = cmd({ return } - const shareData: ShareData[] = await response.json() - const transformed = transformShareData(shareData) + const data = await response.json() - if (!transformed) { + if (!data.info || !data.messages || !Array.isArray(data.messages)) { process.stdout.write(`Share not found or empty: ${slug}`) process.stdout.write(EOL) return } - exportData = transformed + exportData = data + // kilocode_change end } else { exportData = await Filesystem.readJson>(args.file).catch(() => undefined) if (!exportData) { diff --git a/packages/opencode/test/cli/import.test.ts b/packages/opencode/test/cli/import.test.ts index e32de1342e4..21a3fed61a4 100644 --- a/packages/opencode/test/cli/import.test.ts +++ b/packages/opencode/test/cli/import.test.ts @@ -8,16 +8,19 @@ import { } from "../../src/cli/cmd/import" // parseShareUrl tests -test("parses valid share URLs", () => { - expect(parseShareUrl("https://opncd.ai/share/Jsj3hNIW")).toBe("Jsj3hNIW") - expect(parseShareUrl("https://custom.example.com/share/abc123")).toBe("abc123") - expect(parseShareUrl("http://localhost:3000/share/test_id-123")).toBe("test_id-123") +test("parses valid Kilo share URLs", () => { + expect(parseShareUrl("https://app.kilo.ai/s/7a755b04-b0fe-4e66-8b30-0ab52a181bd4")).toBe( + "7a755b04-b0fe-4e66-8b30-0ab52a181bd4", + ) + expect(parseShareUrl("https://app.kilo.ai/s/Jsj3hNIW")).toBe("Jsj3hNIW") + expect(parseShareUrl("https://app.kilo.ai/s/test_id-123")).toBe("test_id-123") }) test("rejects invalid URLs", () => { - expect(parseShareUrl("https://opncd.ai/s/Jsj3hNIW")).toBeNull() // legacy format - expect(parseShareUrl("https://opncd.ai/share/")).toBeNull() - expect(parseShareUrl("https://opncd.ai/share/id/extra")).toBeNull() + expect(parseShareUrl("https://app.kilo.ai/s/")).toBeNull() + expect(parseShareUrl("https://app.kilo.ai/s/id/extra")).toBeNull() + expect(parseShareUrl("https://opncd.ai/share/Jsj3hNIW")).toBeNull() + expect(parseShareUrl("https://other.example.com/s/abc")).toBeNull() expect(parseShareUrl("not-a-url")).toBeNull() })