mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-16 20:31:40 +00:00
* feat: add openclaw promos CLI for ClawHub promotional model offers * fix: harden promos claim auth validation and sanitize remote promo text * fix: enforce promo window client-side and validate slug contract * fix: shell-safe model ref contract and explicit --api-key override * fix: hold promotion aliases to the models alias contract * docs: document argv-credential contract and env alternative for promos claim * fix: enforce provider plugin enablement on the credential-reuse claim path * fix: require plugin install before credential-reuse shortcut in promos claim * fix: run runtime plugin repair on promo defaults and harden identifier parsing * fix: distinct message for contract-invalid promo aliases * fix(cli): validate promotion plugin contracts * fix(cli): recheck promotion window before claim * feat(cli): surface ClawHub promotions in models list via the hosted feed Passive discovery for promotional model offers. A cadence-gated (24h), fail-silent conditional GET of ClawHub's immutable promotions feed snapshot (If-None-Match -> 304, short 2.5s timeout, unauthenticated so CDN caches stay unfragmented) is cached in two new shared-state-DB tables, fully separate from update_check_state. models list renders an 'Available via promotion' group for live offers whose models are not in the user's configured set (including the zero-row fresh-install path), tags claimed models promo / promo ended from provenance recorded at claim time, and prints a one-time notice per newly seen offer; promos list and claim mark offers as seen. Machine outputs stay clean, snapshot sequence is monotonic against stale edges, and claims still revalidate against the live API so the kill switch always wins. * style: satisfy lint on promotions feed additions no-useless-fallback-in-spread on the optional request headers and no-map-spread in claim-provenance row mapping. * fix(cli): harden promotions feed cache * fix(cli): honor live promotion validity
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
/** CLI registration for ClawHub promotional model offers. */
|
|
import type { Command } from "commander";
|
|
import { formatDocsLink } from "../../packages/terminal-core/src/links.js";
|
|
import { theme } from "../../packages/terminal-core/src/theme.js";
|
|
import { defaultRuntime } from "../runtime.js";
|
|
import { runCommandWithRuntime } from "./cli-utils.js";
|
|
|
|
export function registerPromosCli(program: Command) {
|
|
const promos = program
|
|
.command("promos")
|
|
.description("Discover and claim promotional model offers from ClawHub")
|
|
.addHelpText(
|
|
"after",
|
|
() =>
|
|
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/promos", "docs.openclaw.ai/cli/promos")}\n`,
|
|
);
|
|
|
|
promos
|
|
.command("list")
|
|
.description("List active promotions")
|
|
.option("--json", "Output JSON", false)
|
|
.action(async (opts: { json?: boolean }) => {
|
|
await runCommandWithRuntime(defaultRuntime, async () => {
|
|
const { promosListCommand } = await import("../commands/promos/list.js");
|
|
await promosListCommand(opts, defaultRuntime);
|
|
});
|
|
});
|
|
|
|
promos
|
|
.command("claim")
|
|
.description("Claim a promotion: set up provider auth and register its models")
|
|
.argument("<slug>", "Promotion slug from `openclaw promos list`")
|
|
// Credential-on-argv matches the shipped `onboard --<provider>-api-key` /
|
|
// `onboard --token` non-interactive contract (AGENTS.md: public API). The
|
|
// no-argv alternative is the provider's env var, detected as existing auth.
|
|
.option("--api-key <key>", "Provider API key for non-interactive setup")
|
|
.option("--set-default", "Set the promotion's suggested model as default without asking", false)
|
|
.action(async (slug: string, opts: { apiKey?: string; setDefault?: boolean }) => {
|
|
await runCommandWithRuntime(defaultRuntime, async () => {
|
|
const { promosClaimCommand } = await import("../commands/promos/claim.js");
|
|
await promosClaimCommand(slug, opts, defaultRuntime);
|
|
});
|
|
});
|
|
}
|