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
107 changes: 107 additions & 0 deletions .github/workflows/package-openai-platform.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: Package release artifacts

on:
push:
tags:
- "**"

permissions:
contents: read

concurrency:
group: package-openai-platform-${{ github.ref }}
cancel-in-progress: false

jobs:
package:
name: Package ChatGPT skills and production marketplace (Python 3.8)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

- name: Set up Python 3.8
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
with:
python-version: "3.8"

- name: Run unit tests
run: python -m unittest discover -s tests -v

- name: Check Python syntax
run: >-
python -m compileall -q
scripts
tests
plugins/codex/lihi/skills/lihi-shorten/scripts
plugins/claude/lihi/skills/lihi-shorten/scripts

- name: Check Codex and Claude parity
run: |
cmp plugins/codex/lihi/skills/lihi-shorten/scripts/detect_urls.py plugins/claude/lihi/skills/lihi-shorten/scripts/detect_urls.py
cmp plugins/codex/lihi/skills/lihi-shorten/references/shortening-workflow.md plugins/claude/lihi/skills/lihi-shorten/references/shortening-workflow.md
cmp plugins/codex/lihi/skills/lihi-switch-group/references/error-recovery.md plugins/claude/lihi/skills/lihi-switch-group/references/error-recovery.md
cmp plugins/codex/lihi/skills/lihi-switch-domain/references/error-recovery.md plugins/claude/lihi/skills/lihi-switch-domain/references/error-recovery.md

- name: Check whitespace errors
run: git diff --check "$(git hash-object -t tree /dev/null)" HEAD -- .

- name: Build OpenAI Platform skill bundles
run: >-
python scripts/package_openai_platform_bundle.py
--output-dir dist/openai-platform

- name: Build production marketplace bundle
run: >-
python scripts/package_production_bundle.py
--output-dir dist/production

- name: Verify tag matches package version
shell: bash
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
if [[ "$RELEASE_TAG" =~ ^v?([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
package_version="${BASH_REMATCH[1]}"
else
echo "::error::Release tag must be a SemVer version such as v0.3.1 or 0.3.1 (got $RELEASE_TAG)."
exit 1
fi

for skill_name in lihi-shorten lihi-account lihi-switch-group lihi-switch-domain; do
skill_zip="dist/openai-platform/${skill_name}-${package_version}.zip"
if [ ! -f "$skill_zip" ]; then
echo "::error::Tag $RELEASE_TAG does not match the shared production manifest version."
exit 1
fi
done

zip_count="$(find dist/openai-platform -maxdepth 1 -type f -name '*.zip' | wc -l | tr -d ' ')"
if [ "$zip_count" != "4" ]; then
echo "::error::Expected four OpenAI skill ZIPs, found $zip_count."
exit 1
fi

production_bundle="dist/production/lihi-agent-${package_version}"
if [ ! -d "$production_bundle" ]; then
echo "::error::Production marketplace bundle version does not match tag $RELEASE_TAG."
exit 1
fi

- name: Upload OpenAI Platform skill bundles
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: lihi-openai-skills-${{ github.ref_name }}
path: dist/openai-platform/*.zip
if-no-files-found: error
retention-days: 90

- name: Upload production marketplace bundle
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: lihi-agent-production-${{ github.ref_name }}
path: dist/production/lihi-agent-*
if-no-files-found: error
include-hidden-files: true
retention-days: 90
25 changes: 22 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,30 @@ AccountStatus requires `group_name:string|null`, `domain:string|null`, `short_ur
- Requests containing `Origin` are no longer rejected solely because of that header. Do not infer complete browser or CORS support from this fact.
- If compaction removes state required for a safe next operation, fail closed and recover the exact state before mutation or release.

## Develop packaging and versioning
## Release packaging and versioning

CI runs Python 3.8 unit tests, confirms parity files, builds a develop bundle, and uploads it for 14 days. The packager:
CI runs Python 3.8 unit tests and parity checks. Develop-branch CI builds a
develop marketplace for 14-day retention. SemVer tag CI builds four public
OpenAI skill ZIPs plus one production marketplace bundle for 90-day retention.

The develop packager:

- derives a shared `major.minor.patch` core from both host manifests;
- rewrites copied identities, endpoints, four skill folders, manifests, marketplaces, and Codex metadata only inside staging;
- emits `DEVELOP_BUILD.json`, where authoritative `skill_names` contains all four develop skills;
- retains singular `skill_name` at root and `plugins[0]` as a deprecated alias equal to `skill_names[0]` for 0.3 compatibility;
- excludes caches and preserves source runtime files unchanged.

The production marketplace packager copies the checked-in production
marketplaces, both host plugins, and public installation guides without
rewriting identities or endpoints. It emits `lihi-agent-<major.minor.patch>`
and fails rather than overwriting an existing output directory.

The OpenAI Platform packager emits exactly four individual skill ZIPs. Each
archive has one same-named top-level skill directory. It does not accept an app
ID and does not emit a complete plugin ZIP, marketplace, manifest, MCP config,
app config, or shared asset.

Both manifests must share core version `0.3.1`. Codex may add one cachebuster suffix. When modifying the Codex bundle, run the plugin-creator cachebuster helper last and validate the plugin. Reinstall only when explicitly requested; after reinstall, test from a new conversation.

Never commit `dist/`, a develop/localhost runtime URL, or a develop identity in production runtime configuration.
Expand All @@ -127,4 +141,9 @@ cmp plugins/codex/lihi/skills/lihi-shorten/references/shortening-workflow.md plu
git diff --check
```

For packaging changes, also build locally with `scripts/package_develop_bundle.py` and validate all eight skills, both host plugins, production/develop identity isolation, endpoint isolation, metadata aliases, and absence of removed tool fields and stale policies.
For packaging changes, also build locally with
`scripts/package_develop_bundle.py`, `scripts/package_production_bundle.py`,
and `scripts/package_openai_platform_bundle.py`. Validate all host plugins,
production/develop identity isolation, endpoint isolation, metadata aliases,
the four skill-only OpenAI archives, and absence of removed tool fields and
stale policies.
6 changes: 3 additions & 3 deletions README.zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@ https://app.lihi.io/mcp/v1/tools

## 安裝

正式環境市集來源為 [weedgood/lihi-agent-plugin.git](https://github.com/weedgood/lihi-agent-plugin.git)。外掛選擇器為 `lihi@lihi`,顯示名稱為 `lihi`。
正式環境市集來源為 [lihi-io/lihi-agent-plugin.git](https://github.com/lihi-io/lihi-agent-plugin.git)。外掛選擇器為 `lihi@lihi`,顯示名稱為 `lihi`。

### 直接從 GitHub 安裝

#### Codex

```bash
codex plugin marketplace add https://github.com/weedgood/lihi-agent-plugin.git
codex plugin marketplace add https://github.com/lihi-io/lihi-agent-plugin.git
codex plugin add lihi@lihi
```

#### Claude Code

```bash
claude plugin marketplace add https://github.com/weedgood/lihi-agent-plugin.git
claude plugin marketplace add https://github.com/lihi-io/lihi-agent-plugin.git
claude plugin install lihi@lihi
```

Expand Down
112 changes: 112 additions & 0 deletions docs/openai-platform-packaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# OpenAI Platform skill packaging

The public lihi directory submission uses the OpenAI Platform **With MCP**
flow. The submission portal owns the production MCP registration, listing
information, and brand assets. The repository packager produces only the four
final skill bundles.

## Build the skill ZIPs

Run from the repository root:

```bash
python3 scripts/package_openai_platform_bundle.py \
--output-dir dist/openai-platform
```

The script derives the shared `major.minor.patch` version from the Codex and
Claude production manifests. For version `0.3.1`, the only outputs are:

```text
dist/openai-platform/lihi-shorten-0.3.1.zip
dist/openai-platform/lihi-account-0.3.1.zip
dist/openai-platform/lihi-switch-group-0.3.1.zip
dist/openai-platform/lihi-switch-domain-0.3.1.zip
```

Each ZIP contains exactly one same-named top-level skill directory. For
example, `lihi-shorten-0.3.1.zip` contains `lihi-shorten/SKILL.md` plus that
skill's approved `agents/`, `references/`, and `scripts/` files.

The packager does not accept an app ID and does not create a complete plugin,
Developer marketplace, manifest, shared asset, `.mcp.json`, or `.app.json`.
The checked-in images under `packaging/openai-platform/assets/` remain
available for manual use in the submission portal, but are not packaging
inputs and do not block skill builds.

The source skills remain unchanged and are the single source of truth. The
packager reads approved files directly from each Codex production skill,
stages exact host-neutral rewrites, and validates each archive before replacing
any existing generated skill ZIP. All four archives use sorted files, fixed ZIP
timestamps, and consistent permissions for reproducible bytes.

The public skill bundles remove the pricing and dedicated-domain promotional
link sentences without inserting replacement service copy. Quota recovery
keeps its existing account-limit explanation without directing users to a
sales page.

## Build the production marketplace bundle

The production marketplace for Codex and Claude Code is packaged separately:

```bash
python3 scripts/package_production_bundle.py \
--output-dir dist/production
```

For version `0.3.1`, this creates:

```text
dist/production/lihi-agent-0.3.1/
```

This installable directory retains the production `lihi@lihi` marketplace,
the `lihi` MCP identity, all four production skill names, and
`https://app.lihi.io/mcp/v1/tools`. It contains both Codex and Claude Code
plugin roots. The existing `package_develop_bundle.py` remains isolated to the
`lihi-dev` identity and the lihidev endpoint.

## Build from a release tag

Pushing a SemVer tag runs `.github/workflows/package-openai-platform.yml`.
Both `v0.3.1` and `0.3.1` tag forms are accepted. The tag must match the shared
Codex and Claude production manifest version.

```bash
git tag v0.3.1
git push origin v0.3.1
```

The workflow runs unit tests, syntax checks, host parity checks, and whitespace
validation. It uploads two GitHub Actions artifacts for 90 days:

- `lihi-openai-skills-<tag>` contains the four individual skill ZIPs.
- `lihi-agent-production-<tag>` contains the installable production
marketplace bundle.

The workflow does not create or modify a GitHub Release.

## Submit with MCP

In the OpenAI submission portal:

1. Choose **With MCP** and provide
`https://app.lihi.io/mcp/v1/tools` as the production server URL.
2. Upload each final skill ZIP in its corresponding skill upload flow.
3. Provide the listing logo, website, support, privacy, and terms information
directly in the portal.
4. Complete the domain-verification challenge and production tool scan.
5. Provide exactly five positive test cases, three negative test cases,
release notes, and any requested demo recording.
6. Confirm every tool publishes accurate `readOnlyHint`, `openWorldHint`, and
`destructiveHint` annotations with justifications.
7. Provide reviewer-ready demo credentials for the OAuth flow.

A successful local build validates only the static skill and marketplace
artifacts. It does not validate the live MCP server, domain challenge, reviewer
credentials, policy attestations, or portal review.

See the official OpenAI documentation for
[plugin submission](https://developers.openai.com/plugins/deploy/submission)
and
[submission validation errors](https://developers.openai.com/plugins/deploy/submission-errors).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packaging/openai-platform/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 9 additions & 13 deletions scripts/package_develop_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,13 @@
)

TEXT_SUFFIXES = {".json", ".md", ".yaml", ".yml"}
PACKAGE_IGNORE = shutil.ignore_patterns("__pycache__", "*.pyc", "*.pyo", ".DS_Store")
PACKAGE_IGNORE = shutil.ignore_patterns(
"__pycache__",
"*.pyc",
"*.pyo",
".DS_Store",
"openai-platform-packaging.md",
)
SEMVER_PATTERN = re.compile(
r"^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"
r"(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$"
Expand Down Expand Up @@ -751,8 +757,8 @@ def rewrite_develop_readme(staging_root: Path) -> None:
(
Path("README.zh-TW.md"),
(
"正式環境市集來源為 [weedgood/lihi-agent-plugin.git]"
"(https://github.com/weedgood/lihi-agent-plugin.git)。"
"正式環境市集來源為 [lihi-io/lihi-agent-plugin.git]"
"(https://github.com/lihi-io/lihi-agent-plugin.git)。"
"外掛選擇器為 `{0}`,顯示名稱為 `{1}`。".format(
DEVELOP_PLUGIN_SELECTOR,
DEVELOP_DISPLAY_NAME,
Expand All @@ -777,21 +783,11 @@ def rewrite_develop_readme(staging_root: Path) -> None:
)
)
updated = content.replace(source_sentence, develop_sentence)
updated = updated.replace(
"codex plugin marketplace add "
"https://github.com/weedgood/lihi-agent-plugin.git",
"codex plugin marketplace add .",
)
updated = updated.replace(
"codex plugin marketplace add "
"https://github.com/lihi-io/lihi-agent-plugin.git",
"codex plugin marketplace add .",
)
updated = updated.replace(
"claude plugin marketplace add "
"https://github.com/weedgood/lihi-agent-plugin.git",
"claude plugin marketplace add .",
)
updated = updated.replace(
"claude plugin marketplace add "
"https://github.com/lihi-io/lihi-agent-plugin.git",
Expand Down
Loading