Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<p align="center">
<a href="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml"><img src="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/v/ascendho.threadrelink?label=Marketplace&logo=visualstudiocode" alt="Visual Studio Marketplace version"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/i/ascendho.threadrelink?logo=visualstudiocode" alt="Visual Studio Marketplace installs"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/badge/VS_Code-Marketplace-007ACC?logo=visualstudiocode&logoColor=white" alt="Get ThreadRelink from the VS Code Marketplace"></a>
<a href="https://github.com/ascendho/ThreadRelink/releases/latest"><img src="https://img.shields.io/github/v/release/ascendho/ThreadRelink?label=Release" alt="Latest GitHub release"></a>
<a href="LICENSE"><img src="https://img.shields.io/github/license/ascendho/ThreadRelink" alt="MIT License"></a>
</p>

Expand Down Expand Up @@ -105,27 +105,6 @@ codex resume --cd /new/path/finspec <thread-id>
ThreadRelink never automatically treats a nested folder as its parent Git
repository.

## Migrating from RepoRecall

ThreadRelink `0.4.0` recognizes existing RepoRecall data:

- `~/.reporecall/registry.json`
- `reporecall.projectId` in local Git configuration
- `.reporecall/project.json`
- `REPORECALL_HOME` and `REPORECALL_CODEX_PATH`

When the new location is absent, valid legacy data is copied to the
ThreadRelink namespace with the same project UUID. Existing new data is never
overwritten, and legacy files remain available as a rollback copy.

The renamed VS Code extension has a new extension ID. Uninstall the old
RepoRecall VSIX after installing ThreadRelink to avoid duplicate Activity Bar
views. VS Code asks for metadata consent again, but this does not affect Codex
transcripts or migrated project links.

Legacy `reporecall` CLI and command aliases remain available for one
compatibility release.

## CLI

Requirements:
Expand Down Expand Up @@ -190,8 +169,9 @@ pnpm package:vscode

CI runs checks and VSIX packaging on macOS, Linux, and Windows.
Publishing is triggered by a matching `vX.Y.Z` GitHub Release after all checks
pass. See [Marketplace publishing](docs/MARKETPLACE_PUBLISHING.md) for the
one-time identity setup and release procedure.
pass. See the
[Marketplace publishing guide (Chinese)](docs/MARKETPLACE_PUBLISHING.md) for
the one-time identity setup and release procedure.

## License

Expand Down
22 changes: 2 additions & 20 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<p align="center">
<a href="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml"><img src="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/v/ascendho.threadrelink?label=Marketplace&logo=visualstudiocode" alt="Visual Studio Marketplace 版本"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/i/ascendho.threadrelink?logo=visualstudiocode" alt="Visual Studio Marketplace 安装量"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/badge/VS_Code-Marketplace-007ACC?logo=visualstudiocode&logoColor=white" alt="从 VS Code Marketplace 获取 ThreadRelink"></a>
<a href="https://github.com/ascendho/ThreadRelink/releases/latest"><img src="https://img.shields.io/github/v/release/ascendho/ThreadRelink?label=Release" alt="最新 GitHub Release"></a>
<a href="LICENSE"><img src="https://img.shields.io/github/license/ascendho/ThreadRelink" alt="MIT License"></a>
</p>

Expand Down Expand Up @@ -95,24 +95,6 @@ codex resume --cd /new/path/finspec <thread-id>

ThreadRelink 不会自动把嵌套文件夹当成父级 Git 仓库。

## 从 RepoRecall 迁移

ThreadRelink `0.4.0` 可以识别以下旧数据:

- `~/.reporecall/registry.json`
- Git 本地配置中的 `reporecall.projectId`
- `.reporecall/project.json`
- `REPORECALL_HOME` 和 `REPORECALL_CODEX_PATH`

如果新位置还没有数据,ThreadRelink 会验证旧数据,并使用相同 UUID 将其复制到
新命名空间。已有的新数据不会被覆盖,旧文件也会保留,方便回退。

新版 VS Code 扩展使用新的扩展 ID。安装 ThreadRelink 后,请卸载旧的 RepoRecall
VSIX,避免活动栏同时出现两个入口。VS Code 会重新询问一次元数据授权,但这不会
影响 Codex 聊天文件和已经迁移的项目关联。

旧的 `reporecall` CLI 和命令别名会继续兼容一个版本。

## CLI

要求:
Expand Down
90 changes: 36 additions & 54 deletions docs/MARKETPLACE_PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
# Marketplace publishing
# Marketplace 发布

ThreadRelink is published as `ascendho.threadrelink`. A GitHub Release whose tag
matches the extension version publishes the VSIX to the Visual Studio
Marketplace and attaches the same package to the GitHub Release.
ThreadRelink `ascendho.threadrelink` 发布。创建与扩展版本一致的 GitHub
Release 后,自动化工作流会把 VSIX 发布到 Visual Studio Marketplace,并将同一
文件添加到 GitHub Release

Marketplace installs receive VS Code extension updates automatically. A
manually installed VSIX does not receive automatic updates by default.
通过 Marketplace 安装的扩展会随 VS Code 自动更新。手动安装的 VSIX 默认不会
自动更新。

## One-time identity setup
## 一次性身份配置

The publishing workflow uses Microsoft Entra ID and GitHub OIDC. It does not
store a Personal Access Token.
发布工作流使用 Microsoft Entra ID GitHub OIDC,不保存 Personal Access
Token

1. Sign in to Azure DevOps and the Visual Studio Marketplace with the same
Microsoft account.
2. Create the Marketplace publisher `ascendho`. Publisher IDs cannot be renamed.
3. In an Azure subscription, create a resource group and a user-assigned managed
identity:
1. 使用同一个 Microsoft 账户登录 Azure DevOps 和 Visual Studio Marketplace。
2. 创建 Marketplace publisher `ascendho`。Publisher ID 创建后无法修改。
3. 在 Azure subscription 中创建 resource group 和 user-assigned managed
identity:

```bash
az group create \
Expand All @@ -28,9 +27,8 @@ store a Personal Access Token.
--resource-group threadrelink-publishing
```

4. Give the identity Reader access to the subscription. Replace the
placeholders with values returned by `az account show` and
`az identity show`:
4. 为该 identity 授予 subscription 的 Reader 权限。将占位符替换为
`az account show` 和 `az identity show` 返回的值:

```bash
az role assignment create \
Expand All @@ -40,8 +38,8 @@ store a Personal Access Token.
--scope /subscriptions/<SUBSCRIPTION_ID>
```

5. Add a federated credential that trusts only the `marketplace` GitHub
Environment in this repository:
5. 添加 federated credential,只信任本仓库的 `marketplace` GitHub
Environment

```bash
az identity federated-credential create \
Expand All @@ -53,54 +51,38 @@ store a Personal Access Token.
--audiences api://AzureADTokenExchange
```

This repository uses GitHub's immutable owner and repository IDs in OIDC
subjects. The numeric IDs remain stable if the owner or repository is
renamed. A fork or transferred repository must use the subject shown in its
own GitHub OIDC assertion.
OIDC subject 使用 GitHub 不可变的 owner ID 和 repository ID。即使 owner
或仓库改名,这些数字 ID 也不会变化。Fork 或转移仓库后,必须改用该仓库自身
GitHub OIDC assertion 中的 subject。

6. Create a GitHub Environment named `marketplace`. Restrict its deployment
tags to `v*`, then add these non-secret environment variables:
6. 创建名为 `marketplace` 的 GitHub Environment,将 deployment tag 限制为
`v*`,并添加以下非敏感环境变量:

- `AZURE_CLIENT_ID`
- `AZURE_TENANT_ID`
- `AZURE_SUBSCRIPTION_ID`

7. Run **Check Marketplace Publishing Identity** with `verify_access` set to
`false`. Copy the Marketplace profile ID shown in the workflow summary.
8. In the Marketplace publisher management page, add that profile ID as a
member of `ascendho` with the Contributor role.
9. Run the identity check again with `verify_access` set to `true`. Do not create
a release until this check succeeds.
7. 运行 **Check Marketplace Publishing Identity**,将 `verify_access` 设置为
`false`,并复制 workflow summary 中显示的 Marketplace profile ID
8. Marketplace publisher 管理页面中,将该 profile ID 添加为 `ascendho`
Contributor
9. 再次运行身份检查,将 `verify_access` 设置为 `true`。检查成功前不要创建
Release。

## Publish a version
## 发布新版本

1. Update `packages/vscode/package.json` to the new `X.Y.Z` version.
2. Add the same version heading to `packages/vscode/CHANGELOG.md`.
3. Run:
1. `packages/vscode/package.json` 更新为新的 `X.Y.Z` 版本。
2. `packages/vscode/CHANGELOG.md` 中添加相同的版本标题。
3. 运行:

```bash
pnpm check
pnpm check:release-version vX.Y.Z
pnpm package:vscode
```

4. Merge the release commit into `main`.
5. Create and publish a GitHub Release whose tag is exactly `vX.Y.Z`.
4. release commit 合并到 `main`
5. 创建并发布 Tag 恰好为 `vX.Y.Z` 的 GitHub Release。

The release workflow repeats all checks, attaches `threadrelink.vsix`, and
publishes the same package to the Marketplace. Duplicate workflow retries are
safe because publishing uses `--skip-duplicate`.

## First Marketplace installation

The development VSIX used the old extension ID
`ascendho.threadrelink-vscode`. Uninstall it once, then install the Marketplace
edition:

```bash
code --uninstall-extension ascendho.threadrelink-vscode
code --install-extension ascendho.threadrelink
```

This changes only the installed extension identity. ThreadRelink's registry,
stable project UUIDs, and Codex conversation files are preserved.
Release 工作流会重新执行全部检查、附加 `threadrelink.vsix`,并将同一个包发布到
Marketplace。发布命令使用 `--skip-duplicate`,因此重复运行工作流是安全的。
14 changes: 2 additions & 12 deletions packages/vscode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<p align="center">
<a href="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml"><img src="https://github.com/ascendho/ThreadRelink/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/v/ascendho.threadrelink?label=Marketplace&logo=visualstudiocode" alt="Visual Studio Marketplace version"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/visual-studio-marketplace/i/ascendho.threadrelink?logo=visualstudiocode" alt="Visual Studio Marketplace installs"></a>
<a href="https://marketplace.visualstudio.com/items?itemName=ascendho.threadrelink"><img src="https://img.shields.io/badge/VS_Code-Marketplace-007ACC?logo=visualstudiocode&logoColor=white" alt="Get ThreadRelink from the VS Code Marketplace"></a>
<a href="https://github.com/ascendho/ThreadRelink/releases/latest"><img src="https://img.shields.io/github/v/release/ascendho/ThreadRelink?label=Release" alt="Latest GitHub release"></a>
<a href="https://github.com/ascendho/ThreadRelink/blob/main/LICENSE"><img src="https://img.shields.io/github/license/ascendho/ThreadRelink" alt="MIT License"></a>
</p>

Expand Down Expand Up @@ -65,16 +65,6 @@ codex resume --cd <current-project-path> <thread-id>
An unconfigured project never displays all global conversations. A nested
folder also never inherits a parent Git project without an explicit choice.

## Upgrading from RepoRecall

ThreadRelink migrates valid RepoRecall registry, Git project IDs, and directory
identity files while preserving their UUIDs. Existing ThreadRelink data is
never overwritten, and legacy files remain as a rollback copy.

This renamed extension has a new extension ID. Remove the old RepoRecall VSIX
after installing ThreadRelink to avoid duplicate Activity Bar entries. Metadata
consent is requested again for the new extension.

## Privacy

ThreadRelink reads thread ID, title/preview, timestamps, recorded cwd, archive
Expand Down
2 changes: 1 addition & 1 deletion packages/vscode/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "threadrelink",
"displayName": "ThreadRelink",
"description": "Keep local Codex conversations discoverable after a repository is renamed or moved.",
"description": "A VS Code extension that keeps local Codex conversations discoverable after a repository is renamed or moved.",
"version": "0.4.0",
"icon": "resources/threadrelink.png",
"publisher": "ascendho",
Expand Down
4 changes: 4 additions & 0 deletions packages/vscode/test/manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface WalkthroughStep {
interface ExtensionManifest {
name: string;
displayName: string;
description: string;
version: string;
icon: string;
pricing: string;
Expand Down Expand Up @@ -44,6 +45,9 @@ describe("VS Code extension manifest", () => {
expect(manifest.name).toBe("threadrelink");
expect(manifest.publisher).toBe("ascendho");
expect(manifest.displayName).toBe("ThreadRelink");
expect(manifest.description).toBe(
"A VS Code extension that keeps local Codex conversations discoverable after a repository is renamed or moved.",
);
expect(manifest.version).toMatch(/^\d+\.\d+\.\d+$/);
expect(manifest.pricing).toBe("Free");
expect(manifest.galleryBanner).toEqual({
Expand Down