From 1e02478d1f2310ed5a9b5a62d34e169f103a8791 Mon Sep 17 00:00:00 2001 From: EthanHuo Date: Thu, 12 Nov 2026 23:49:36 +0800 Subject: [PATCH] chore: upgrade @celados/argc to 11.0.0 (flat @schema), compact --schema natively, release 0.4.0 - schema.ts: drop regex post-processing of the old JSDoc output; root view is a compact router (no doctor), selectors render full. - --schema root: 1970 -> 2340 bytes (flat Markdown headings), budget 2000 -> 2500. - examples: drop trivial operations list/show examples; describe/docs keep the flag-form. --- bun.lock | 6 +- package.json | 2 +- packages/gkit/package.json | 4 +- packages/gkit/src/cli.test.ts | 17 +- packages/gkit/src/schema.ts | 347 ++++++++-------------------------- 5 files changed, 91 insertions(+), 285 deletions(-) diff --git a/bun.lock b/bun.lock index f0a3013..a20ee64 100644 --- a/bun.lock +++ b/bun.lock @@ -19,7 +19,7 @@ "gkit": "dist/gkit.js", }, "devDependencies": { - "@celados/argc": "^10.2.0", + "@celados/argc": "^11.0.0", "@standard-schema/spec": "^1.0.0", "@types/bun": "^1.3.10", "@types/node": "^25.6.0", @@ -39,7 +39,7 @@ }, }, "catalog": { - "@celados/argc": "^10.2.0", + "@celados/argc": "^11.0.0", "@types/bun": "^1.3.10", "@types/node": "^25.6.0", "@valibot/to-json-schema": "^1.6.0", @@ -54,7 +54,7 @@ "yaml": "^2.9.0", }, "packages": { - "@celados/argc": ["@celados/argc@10.2.0", "https://npm.celados.com/@celados/argc/-/@celados/argc-10.2.0.tgz", { "dependencies": { "yaml": "^2.9.1" }, "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@valibot/to-json-schema": "^1.8.0", "valibot": "^1.5.0" } }, "sha512-cRjltgtnTDmM9WAUQ3Xgm/076R5qns6F+vkzmGxzOnZbY+HiPYAR2nXBsjSbWvBdsmi6gK/oe44NQHjXANBbQw=="], + "@celados/argc": ["@celados/argc@11.0.0", "https://npm.celados.com/@celados/argc/-/@celados/argc-11.0.0.tgz", { "dependencies": { "yaml": "^2.9.1" }, "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@valibot/to-json-schema": "^1.8.0", "valibot": "^1.5.0" } }, "sha512-376S0EpKHXV00RLGmQuMfuYYZBLgWIAHngpdmGAbGAn5FBhHNeKd5Lg9XNdv/qtTfIwlONOLnfyt4QTM1Gw3ZA=="], "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], diff --git a/package.json b/package.json index 1138b9c..de9ce5e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "@types/node": "^25.6.0", "@valibot/to-json-schema": "^1.6.0", "ajv": "^8.20.0", - "@celados/argc": "^10.2.0", + "@celados/argc": "^11.0.0", "bun-types": "^1.3.13", "dataforseo-client": "^2.0.25", "dotenv": "^17.2.2", diff --git a/packages/gkit/package.json b/packages/gkit/package.json index fa568ed..255cc85 100644 --- a/packages/gkit/package.json +++ b/packages/gkit/package.json @@ -1,6 +1,6 @@ { "name": "gkit", - "version": "0.3.6", + "version": "0.4.0", "private": true, "description": "Profile-bound, agent-first growth provider CLI.", "bin": { @@ -37,7 +37,7 @@ "test:site": "bun run ./scripts/test-site-snapshot.ts" }, "devDependencies": { - "@celados/argc": "^10.2.0", + "@celados/argc": "^11.0.0", "@standard-schema/spec": "^1.0.0", "@types/bun": "^1.3.10", "@types/node": "^25.6.0", diff --git a/packages/gkit/src/cli.test.ts b/packages/gkit/src/cli.test.ts index 5f1aaa9..8e29dde 100644 --- a/packages/gkit/src/cli.test.ts +++ b/packages/gkit/src/cli.test.ts @@ -25,14 +25,15 @@ describe("gkit process contract", () => { expect(result.exitCode).toBe(0); expect(result.stderr).toBe(""); - expect(Buffer.byteLength(result.stdout)).toBeLessThan(2_000); + expect(Buffer.byteLength(result.stdout)).toBeLessThan(2_500); expect(result.stdout).toContain("gkit --profile dataforseo api call"); expect(result.stdout).toContain("gkit --profile posthog api call"); expect(result.stdout).toContain("gkit --profile google-ads api call"); expect(result.stdout).toContain("gkit --profile bing api call"); expect(result.stdout).toContain("gkit --profile gsc api call"); expect(result.stdout).toContain("gkit --profile hubspot api call"); - expect(result.stdout).toContain("pagespeed: {"); + expect(result.stdout).toContain("### pagespeed.api.call"); + expect(result.stdout).not.toContain("pagespeed.doctor"); expect(result.stdout).toContain("gkit describe --id "); expect(result.stdout).toContain("argc dotted commands are intentionally not exposed"); expect(result.stdout).not.toContain("gkit dataforseo.api.call"); @@ -43,18 +44,18 @@ describe("gkit process contract", () => { const selected = await runCli(["--schema", "posthog"], fixture.env); expect(selected.exitCode).toBe(0); - expect(selected.stdout).toContain("posthog:"); - expect(selected.stdout).not.toContain("dataforseo:"); + expect(selected.stdout).toContain("### posthog.api.call"); + expect(selected.stdout).not.toContain("dataforseo"); const googleAds = await runCli(["--schema", "google-ads"], fixture.env); expect(googleAds.exitCode).toBe(0); - expect(googleAds.stdout).toContain('"google-ads":'); - expect(googleAds.stdout).not.toContain("posthog:"); + expect(googleAds.stdout).toContain("### google-ads.api.call"); + expect(googleAds.stdout).not.toContain("posthog"); const hubspot = await runCli(["--schema", "hubspot"], fixture.env); expect(hubspot.exitCode).toBe(0); - expect(hubspot.stdout).toContain("hubspot:"); - expect(hubspot.stdout).not.toContain("posthog:"); + expect(hubspot.stdout).toContain("### hubspot.api.call"); + expect(hubspot.stdout).not.toContain("posthog"); }); it("dispatches HubSpot through the common api call envelope and artifact contract", async () => { diff --git a/packages/gkit/src/schema.ts b/packages/gkit/src/schema.ts index 7839de4..73d6893 100644 --- a/packages/gkit/src/schema.ts +++ b/packages/gkit/src/schema.ts @@ -10,6 +10,7 @@ const s = toStandardJsonSchema; export function buildGkitSchema( manifest: LoadedExecutableManifest | readonly LoadedExecutableManifest[], + { compact = false }: { compact?: boolean } = {}, ): Router { const manifests = Array.isArray(manifest) ? manifest : [manifest]; const capabilities = manifests.flatMap((candidate) => candidate.document.capabilities); @@ -38,40 +39,63 @@ export function buildGkitSchema( }); } + const provider = (description: string, doctorProfile: string, name: string, callFlags: string) => + group( + { description }, + { + ...(compact + ? {} + : { + doctor: c + .meta({ + description: "Profile check.", + examples: [`gkit --profile ${doctorProfile} ${name} doctor`], + }) + .input(s(v.strictObject({}))), + }), + api: group( + {}, + { + call: c + .meta({ + description: "Call a reviewed capability.", + examples: [ + `gkit --profile ${name} api call ${callFlags} --out --dry-run`, + ], + }) + .input(s(v.strictObject({}))), + }, + ), + }, + ); + const idFlags = "--capability-id --input @request.json"; + return { site: siteRouter, describe: c .meta({ description: "Capability details.", - examples: ["gkit describe --id dataforseo.backlinks.bulk_ranks.live"], + examples: ["gkit describe --id "], }) .input(s(v.strictObject({ id: v.string() }))), docs: c .meta({ description: "Provider docs directory.", - examples: ["gkit docs --provider dataforseo"], + examples: ["gkit docs --provider "], }) .input(s(v.strictObject({ provider: v.optional(v.string()) }))), operations: group( { description: "Journal." }, { - list: c - .meta({ - description: "Summary.", - examples: ["gkit operations"], - }) - .input(s(v.strictObject({}))), + list: c.meta({ description: "Summary." }).input(s(v.strictObject({}))), show: c - .meta({ - description: "One operation.", - examples: ["gkit operations show --id "], - }) + .meta({ description: "One operation." }) .input(s(v.strictObject({ id: v.string() }))), reconcile: c .meta({ description: "Manual settlement.", examples: [ - "gkit operations reconcile --id --result succeeded --evidence-ref ticket:123", + "gkit operations reconcile --id [--result ] [--spend-outcome [--cost-usd ]] --evidence-ref ", ], }) .input( @@ -79,7 +103,9 @@ export function buildGkitSchema( v.strictObject({ id: v.string(), result: v.optional(v.picklist(["succeeded", "failed", "not_dispatched"])), - spendOutcome: v.optional(v.picklist(["confirmed_charged", "confirmed_not_charged"])), + spendOutcome: v.optional( + v.picklist(["confirmed_charged", "confirmed_not_charged"]), + ), evidenceRef: v.string(), costUsd: v.optional(v.string()), providerRequestId: v.optional(v.string()), @@ -88,174 +114,37 @@ export function buildGkitSchema( ), }, ), - dataforseo: group( - { description: `${dataForSeoCapabilityCount} reviewed reads.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile app-a dataforseo doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "gkit --profile dataforseo api call --capability-id --input @request.json --allow-spend --max-spend-usd --out --dry-run.", - examples: [ - "gkit --profile dataforseo api call --capability-id --input @request.json --allow-spend --max-spend-usd --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, - ), - bing: group( - { description: `${bingCapabilityCount} reviewed reads.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile app-a bing doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "gkit --profile bing api call --capability-id --input @request.json --out --dry-run.", - examples: [ - "gkit --profile bing api call --capability-id --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, - ), - posthog: group( - { description: "1 reviewed read." }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile app-a posthog doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: - "gkit --profile posthog api call --capability-id posthog.query.run --input @request.json --out --dry-run.", - examples: [ - "gkit --profile posthog api call --capability-id posthog.query.run --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, + dataforseo: provider( + `${dataForSeoCapabilityCount} reviewed reads.`, + "app-a", + "dataforseo", + `${idFlags} --allow-spend --max-spend-usd `, ), - "google-ads": group( - { description: `${googleAdsCapabilityCount} reviewed reads.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile openclaw-web google-ads doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "gkit --profile google-ads api call --capability-id --input @request.json --out --dry-run.", - examples: [ - "gkit --profile google-ads api call --capability-id --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, + bing: provider(`${bingCapabilityCount} reviewed reads.`, "app-a", "bing", idFlags), + posthog: provider( + "1 reviewed read.", + "app-a", + "posthog", + "--capability-id posthog.query.run --input @request.json", ), - gsc: group( - { description: `${gscCapabilityCount} reviewed capabilities; writes need --allow-write.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile openclaw-web gsc doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "gkit --profile gsc api call --capability-id --input @request.json --out --dry-run.", - examples: [ - "gkit --profile gsc api call --capability-id --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, + "google-ads": provider( + `${googleAdsCapabilityCount} reviewed reads.`, + "openclaw-web", + "google-ads", + idFlags, ), - hubspot: group( - { description: `${hubSpotCapabilityCount} reviewed reads.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile app-a hubspot doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "gkit --profile hubspot api call --capability-id --input @request.json --out --dry-run.", - examples: [ - "gkit --profile hubspot api call --capability-id --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, + gsc: provider( + `${gscCapabilityCount} reviewed capabilities; writes need --allow-write.`, + "openclaw-web", + "gsc", + idFlags, ), - pagespeed: group( - { description: `${pageSpeedCapabilityCount} reviewed reads.` }, - { - doctor: c - .meta({ - description: "Profile check.", - examples: ["gkit --profile app-a pagespeed doctor"], - }) - .input(s(v.strictObject({}))), - api: group( - { description: "Native API." }, - { - call: c - .meta({ - description: "Call pagespeed.run.", - examples: [ - "gkit --profile pagespeed api call --capability-id pagespeed.run --input @request.json --out --dry-run", - ], - }) - .input(s(v.strictObject({}))), - }, - ), - }, + hubspot: provider(`${hubSpotCapabilityCount} reviewed reads.`, "app-a", "hubspot", idFlags), + pagespeed: provider( + `${pageSpeedCapabilityCount} reviewed reads.`, + "app-a", + "pagespeed", + "--capability-id pagespeed.run --input @request.json", ), }; } @@ -264,19 +153,17 @@ export function renderGkitSchema( manifest: LoadedExecutableManifest | readonly LoadedExecutableManifest[], selector: string | null, ): string { - const root = buildGkitSchema(manifest); if (!selector) { - const compactRoot = Object.fromEntries( - Object.entries(root).filter(([name]) => name !== "site"), - ); - return `${schemaPreamble()}${compactRootSchema( - rewriteArgcExamples(generateSchema(compactRoot, { name: "gkit" }), manifest).replace( - "type Gkit = {", - "type Gkit = {\n /** gkit --schema site */\n site: {}", + // Root view: the dispatcher shape without `site` (own selector) and doctor noise. + const rest = Object.fromEntries( + Object.entries(buildGkitSchema(manifest, { compact: true })).filter( + ([name]) => name !== "site", ), - )}\n`; + ); + return `${schemaPreamble()}${generateSchema(rest, { name: "gkit" })}\n`; } + const root = buildGkitSchema(manifest); let selected: ReturnType; try { const normalizedSelector = @@ -298,91 +185,9 @@ export function renderGkitSchema( message: `Schema selector ${selector} matched no commands.`, }); } - return `${schemaPreamble()}${rewriteArgcExamples( - generateSchema(selected.schema, { name: "gkit" }), - manifest, - )}\n`; + return `${schemaPreamble()}${generateSchema(selected.schema, { name: "gkit" })}\n`; } function schemaPreamble(): string { - return "/** argc dotted commands are intentionally not exposed. */\n"; -} - -function compactRootSchema(generated: string): string { - return ( - generated - // argc 7.6+ promotes authored examples into JSDoc blocks. Keep the 7.5 - // public surface: drop doctor noise, collapse everything else that is - // not describe / docs. - .replace( - /\n[ \t]*\/\*\*\n[ \t]*\* Profile check\.\n(?:[ \t]*\*\n[ \t]*\* @example\n(?:[ \t]*\* .+\n)+)?[ \t]*\*\/\n/g, - "\n", - ) - .replace( - /^([ \t]*)\/\*\*\n[ \t]*\* ([^\n]+)\n[ \t]*\*\n[ \t]*\* @example\n(?:[ \t]*\* .+\n)+[ \t]*\*\//gm, - (block, indent: string, description: string) => { - if ( - description.startsWith("Capability details.") || - description.startsWith("Provider docs directory.") - ) { - return block; - } - return `${indent}/** ${description} */`; - }, - ) - .replace( - /^\s*\/\*\* (?:\d+ reviewed (?:reads?\.|capabilities; [^*\n]*)|Profile check\.|Native API\.) \*\/\n/gm, - "", - ) - .replace(/\n{2,}/g, "\n") - ); -} - -function rewriteArgcExamples( - generated: string, - _manifest: LoadedExecutableManifest | readonly LoadedExecutableManifest[], -): string { - return generated - .replace(/gkit describe "\{ id: 'value' \}"/g, "gkit describe --id ") - .replace(/gkit describe --id \S+/g, "gkit describe --id ") - .replace(/gkit docs "\{ provider: 'value' \}"/g, "gkit docs --provider ") - .replace(/gkit docs --provider \S+/g, "gkit docs --provider ") - .replace( - /gkit operations reconcile --id --result succeeded --evidence-ref ticket:123/g, - "gkit operations reconcile --id [--result ] [--spend-outcome [--cost-usd ]] --evidence-ref ", - ) - .replace( - /gkit bing\.api\.call "[^"]*"/g, - "gkit --profile bing api call --capability-id --input @request.json --out --dry-run", - ) - .replace( - /gkit operations\.reconcile "[^"]*"/g, - "gkit operations reconcile --id [--result ] [--spend-outcome [--cost-usd ]] --evidence-ref ", - ) - .replace(/gkit operations\.show "[^"]*"/g, "gkit operations show --id ") - .replace(/gkit operations\.list "[^"]*"/g, "gkit operations") - .replace( - /gkit dataforseo\.api\.call "[^"]*"/g, - "gkit --profile dataforseo api call --capability-id --input @request.json --allow-spend --max-spend-usd --out --dry-run", - ) - .replace( - /gkit posthog\.api\.call "[^"]*"/g, - "gkit --profile posthog api call --capability-id posthog.query.run --input @request.json --out --dry-run", - ) - .replace( - /gkit google-ads\.api\.call "[^"]*"/g, - "gkit --profile google-ads api call --capability-id --input @request.json --out --dry-run", - ) - .replace( - /gkit gsc\.api\.call "[^"]*"/g, - "gkit --profile gsc api call --capability-id --input @request.json --out --dry-run", - ) - .replace( - /gkit pagespeed\.api\.call "[^"]*"/g, - "gkit --profile pagespeed api call --capability-id pagespeed.run --input @request.json --out --dry-run", - ) - .replace( - /gkit hubspot\.api\.call "[^"]*"/g, - "gkit --profile hubspot api call --capability-id --input @request.json --out --dry-run", - ); + return "argc dotted commands are intentionally not exposed; run spaced commands with --flags. `gkit --schema site` lists the site commands.\n"; }