dsh-coding-subscription-oauth 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/CONTRIBUTING.md +109 -0
- package/INSTALL.md +220 -0
- package/LICENSE +19 -0
- package/NOTICE +11 -0
- package/README.de.md +254 -0
- package/README.es.md +254 -0
- package/README.fr.md +254 -0
- package/README.ja.md +254 -0
- package/README.ko.md +254 -0
- package/README.md +286 -0
- package/README.pt-BR.md +254 -0
- package/README.ru.md +254 -0
- package/README.zh-CN.md +271 -0
- package/cordis.patch.yml +13 -0
- package/docs/00-project-rules.md +195 -0
- package/docs/02-architecture.md +132 -0
- package/docs/02-architecture.zh-CN.md +128 -0
- package/lib/adapter.d.ts +24 -0
- package/lib/adapter.d.ts.map +1 -0
- package/lib/alias-adapter.d.ts +43 -0
- package/lib/alias-adapter.d.ts.map +1 -0
- package/lib/auth-routes.d.ts +155 -0
- package/lib/auth-routes.d.ts.map +1 -0
- package/lib/auth.d.ts +29 -0
- package/lib/auth.d.ts.map +1 -0
- package/lib/bin.d.ts +6 -0
- package/lib/bin.d.ts.map +1 -0
- package/lib/bin.js +27591 -0
- package/lib/bin.js.map +7 -0
- package/lib/capability-routes.d.ts +43 -0
- package/lib/capability-routes.d.ts.map +1 -0
- package/lib/capability-runtime.d.ts +56 -0
- package/lib/capability-runtime.d.ts.map +1 -0
- package/lib/capability-settings.d.ts +263 -0
- package/lib/capability-settings.d.ts.map +1 -0
- package/lib/capability-tools.d.ts +50 -0
- package/lib/capability-tools.d.ts.map +1 -0
- package/lib/catalog.d.ts +53 -0
- package/lib/catalog.d.ts.map +1 -0
- package/lib/client.js +3 -0
- package/lib/client.js.map +7 -0
- package/lib/codex-http.d.ts +77 -0
- package/lib/codex-http.d.ts.map +1 -0
- package/lib/codex-images.d.ts +109 -0
- package/lib/codex-images.d.ts.map +1 -0
- package/lib/codex-model-capabilities.d.ts +112 -0
- package/lib/codex-model-capabilities.d.ts.map +1 -0
- package/lib/codex-search.d.ts +96 -0
- package/lib/codex-search.d.ts.map +1 -0
- package/lib/codex-usage.d.ts +79 -0
- package/lib/codex-usage.d.ts.map +1 -0
- package/lib/gateway-anthropic-messages.d.ts +8 -0
- package/lib/gateway-anthropic-messages.d.ts.map +1 -0
- package/lib/gateway-auth.d.ts +22 -0
- package/lib/gateway-auth.d.ts.map +1 -0
- package/lib/gateway-backend.d.ts +62 -0
- package/lib/gateway-backend.d.ts.map +1 -0
- package/lib/gateway-body.d.ts +9 -0
- package/lib/gateway-body.d.ts.map +1 -0
- package/lib/gateway-config.d.ts +24 -0
- package/lib/gateway-config.d.ts.map +1 -0
- package/lib/gateway-http.d.ts +16 -0
- package/lib/gateway-http.d.ts.map +1 -0
- package/lib/gateway-openai-chat.d.ts +8 -0
- package/lib/gateway-openai-chat.d.ts.map +1 -0
- package/lib/gateway-openai-responses.d.ts +8 -0
- package/lib/gateway-openai-responses.d.ts.map +1 -0
- package/lib/gateway-parse.d.ts +10 -0
- package/lib/gateway-parse.d.ts.map +1 -0
- package/lib/gateway-protocol.d.ts +47 -0
- package/lib/gateway-protocol.d.ts.map +1 -0
- package/lib/gateway-routes.d.ts +21 -0
- package/lib/gateway-routes.d.ts.map +1 -0
- package/lib/gateway.d.ts +48 -0
- package/lib/gateway.d.ts.map +1 -0
- package/lib/grok-imagine.d.ts +271 -0
- package/lib/grok-imagine.d.ts.map +1 -0
- package/lib/grok-import.d.ts +21 -0
- package/lib/grok-import.d.ts.map +1 -0
- package/lib/http-json.d.ts +10 -0
- package/lib/http-json.d.ts.map +1 -0
- package/lib/ids.d.ts +33 -0
- package/lib/ids.d.ts.map +1 -0
- package/lib/imagine-routes.d.ts +59 -0
- package/lib/imagine-routes.d.ts.map +1 -0
- package/lib/index.d.ts +69 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +35355 -0
- package/lib/index.js.map +7 -0
- package/lib/invariant.d.ts +9 -0
- package/lib/invariant.d.ts.map +1 -0
- package/lib/invariant.js +14 -0
- package/lib/invariant.js.map +7 -0
- package/lib/kimi-errors.d.ts +13 -0
- package/lib/kimi-errors.d.ts.map +1 -0
- package/lib/media-store.d.ts +130 -0
- package/lib/media-store.d.ts.map +1 -0
- package/lib/oauth-import-routes.d.ts +52 -0
- package/lib/oauth-import-routes.d.ts.map +1 -0
- package/lib/oauth-providers.d.ts +26 -0
- package/lib/oauth-providers.d.ts.map +1 -0
- package/lib/oauth-session.d.ts +40 -0
- package/lib/oauth-session.d.ts.map +1 -0
- package/lib/oauth-sources.d.ts +205 -0
- package/lib/oauth-sources.d.ts.map +1 -0
- package/lib/oauth.d.ts +79 -0
- package/lib/oauth.d.ts.map +1 -0
- package/lib/provider.d.ts +38 -0
- package/lib/provider.d.ts.map +1 -0
- package/lib/proxy.d.ts +17 -0
- package/lib/proxy.d.ts.map +1 -0
- package/lib/redact.d.ts +5 -0
- package/lib/redact.d.ts.map +1 -0
- package/lib/session.d.ts +40 -0
- package/lib/session.d.ts.map +1 -0
- package/lib/store.d.ts +46 -0
- package/lib/store.d.ts.map +1 -0
- package/lib/web-origin.d.ts +10 -0
- package/lib/web-origin.d.ts.map +1 -0
- package/lib/web-routes.d.ts +20 -0
- package/lib/web-routes.d.ts.map +1 -0
- package/package.json +185 -0
- package/patches/dsh-agy@0.1.2.patch +25 -0
- package/scripts/release.mjs +166 -0
- package/scripts/smoke-deployed-routes.mjs +146 -0
- package/scripts/verify-deployed-catalog.mjs +87 -0
- package/src/adapter.ts +282 -0
- package/src/alias-adapter.ts +152 -0
- package/src/auth-routes.ts +871 -0
- package/src/auth.ts +67 -0
- package/src/bin.ts +350 -0
- package/src/capability-routes.ts +275 -0
- package/src/capability-runtime.ts +313 -0
- package/src/capability-settings.ts +657 -0
- package/src/capability-tools.ts +666 -0
- package/src/catalog.ts +271 -0
- package/src/client/GrokBuildSettings.tsx +2221 -0
- package/src/client/index.tsx +37 -0
- package/src/client/locales.ts +421 -0
- package/src/codex-http.ts +447 -0
- package/src/codex-images.ts +485 -0
- package/src/codex-model-capabilities.ts +320 -0
- package/src/codex-search.ts +245 -0
- package/src/codex-usage.ts +263 -0
- package/src/gateway-anthropic-messages.ts +84 -0
- package/src/gateway-auth.ts +100 -0
- package/src/gateway-backend.ts +274 -0
- package/src/gateway-body.ts +49 -0
- package/src/gateway-config.ts +76 -0
- package/src/gateway-http.ts +104 -0
- package/src/gateway-openai-chat.ts +124 -0
- package/src/gateway-openai-responses.ts +53 -0
- package/src/gateway-parse.ts +224 -0
- package/src/gateway-protocol.ts +52 -0
- package/src/gateway-routes.ts +152 -0
- package/src/gateway.ts +242 -0
- package/src/grok-imagine.ts +1627 -0
- package/src/grok-import.ts +151 -0
- package/src/http-json.ts +82 -0
- package/src/ids.ts +45 -0
- package/src/imagine-routes.ts +461 -0
- package/src/index.ts +598 -0
- package/src/invariant.ts +17 -0
- package/src/kimi-errors.ts +26 -0
- package/src/media-store.ts +927 -0
- package/src/oauth-import-routes.ts +314 -0
- package/src/oauth-providers.ts +152 -0
- package/src/oauth-session.ts +183 -0
- package/src/oauth-sources.ts +1104 -0
- package/src/oauth.ts +620 -0
- package/src/provider.ts +128 -0
- package/src/proxy.ts +99 -0
- package/src/redact.ts +72 -0
- package/src/session.ts +218 -0
- package/src/store.ts +217 -0
- package/src/web-origin.ts +60 -0
- package/src/web-routes.ts +75 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grok Build provider: a pi-ai provider pointed at the official Grok CLI
|
|
3
|
+
* coding backend (`cli-chat-proxy.grok.com`) carrying the CLI fingerprint
|
|
4
|
+
* headers the risk-control middleware requires.
|
|
5
|
+
* @module dsh-coding-subscription-oauth/provider
|
|
6
|
+
*/
|
|
7
|
+
import type { Api, Model, Provider, ThinkingLevelMap } from "@earendil-works/pi-ai";
|
|
8
|
+
/**
|
|
9
|
+
* Grok Build cannot disable reasoning (`reasoning_effort: "none"` is 400).
|
|
10
|
+
* pi-ai treats an absent `xhigh`/`max` key as unsupported, so those levels
|
|
11
|
+
* must be declared explicitly when the model offers them.
|
|
12
|
+
*/
|
|
13
|
+
export declare function grokBuildReasoningMap(levels: readonly ("low" | "medium" | "high" | "xhigh")[]): ThinkingLevelMap;
|
|
14
|
+
/** Inference backend base URL (Responses API lives under `${baseUrl}/responses`). */
|
|
15
|
+
export declare const GROK_BUILD_BASE_URL = "https://cli-chat-proxy.grok.com/v1";
|
|
16
|
+
/** Account model catalog endpoint fetched by the official CLI. */
|
|
17
|
+
export declare const GROK_BUILD_MODELS_URL = "https://cli-chat-proxy.grok.com/v1/models-v2";
|
|
18
|
+
/**
|
|
19
|
+
* Official Grok CLI version this plugin fingerprints as.
|
|
20
|
+
* Track the `@xai-official/grok` npm release stream; make overridable via
|
|
21
|
+
* GROK_BUILD_CLIENT_VERSION for urgent drift fixes without a release.
|
|
22
|
+
*/
|
|
23
|
+
export declare const GROK_CLIENT_VERSION: string;
|
|
24
|
+
/**
|
|
25
|
+
* Fingerprint headers required by the Grok Build middleware. Missing headers
|
|
26
|
+
* are a known 403 trigger (codex-app-transfer field notes, 2026-07).
|
|
27
|
+
*/
|
|
28
|
+
export declare function grokBuildFingerprintHeaders(): Record<string, string>;
|
|
29
|
+
/** Static baseline catalog, used until a live `/models-v2` listing succeeds. */
|
|
30
|
+
export declare function grokBuildBaselineModels(): Model<"openai-responses">[];
|
|
31
|
+
/**
|
|
32
|
+
* Build the Grok Build pi-ai provider. Auth is apiKey-shaped: the OAuth
|
|
33
|
+
* access token is injected as the bearer key by the surrounding adapter
|
|
34
|
+
* (`Models.getAuth` on the login provider performs refresh under the store
|
|
35
|
+
* lock before the key ever reaches here).
|
|
36
|
+
*/
|
|
37
|
+
export declare function grokBuildProvider(models: readonly Model<Api>[]): Provider;
|
|
38
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAKpF;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,gBAAgB,CAWhH;AAED,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,uCAAuC,CAAC;AAExE,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,iDAAqC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAA8D,CAAC;AAEjG;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOpE;AAED,gFAAgF;AAChF,wBAAgB,uBAAuB,IAAI,KAAK,CAAC,kBAAkB,CAAC,EAAE,CA4CrE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,QAAQ,CAkBzE"}
|
package/lib/proxy.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped egress proxy for coding-subscription OAuth and inference traffic.
|
|
3
|
+
* @module dsh-coding-subscription-oauth/proxy
|
|
4
|
+
*/
|
|
5
|
+
export interface CodingOAuthProxyOptions {
|
|
6
|
+
proxyKimi?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** Install one process-wide dispatcher that proxies only the audited host list. */
|
|
9
|
+
export declare function ensureCodingOAuthProxy(explicit?: string, options?: CodingOAuthProxyOptions): string | undefined;
|
|
10
|
+
/** Backward-compatible name retained for existing callers. */
|
|
11
|
+
export declare function ensureGrokBuildProxy(explicit?: string): string | undefined;
|
|
12
|
+
export declare function codingOAuthProxyInEffect(): string | undefined;
|
|
13
|
+
/** Appended to Grok discovery/token/catalog transport errors when a scoped proxy is installed. */
|
|
14
|
+
export declare function codingOAuthProxyUnreachableHint(): string;
|
|
15
|
+
/** Backward-compatible status accessor. */
|
|
16
|
+
export declare function grokBuildProxyInEffect(): string | undefined;
|
|
17
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwDH,MAAM,WAAW,uBAAuB;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,MAAM,GAAG,SAAS,CAenH;AAED,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,SAAS,CAE7D;AAED,kGAAkG;AAClG,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED,2CAA2C;AAC3C,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAE3D"}
|
package/lib/redact.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Remove token-like strings from an external OAuth diagnostic. */
|
|
2
|
+
/** Strip userinfo from a proxy URL so CLI/logs never print `user:pass@`. */
|
|
3
|
+
export declare function redactProxyUrl(value: string): string;
|
|
4
|
+
export declare function safeMessage(error: unknown): string;
|
|
5
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/redact.ts"],"names":[],"mappings":"AAAA,mEAAmE;AA0CnE,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAclD"}
|
package/lib/session.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared OAuth store + live catalog for the host plugin and CLI.
|
|
3
|
+
* @module dsh-coding-subscription-oauth/session
|
|
4
|
+
*/
|
|
5
|
+
import type { Api, Model, MutableModels, Provider } from "@earendil-works/pi-ai";
|
|
6
|
+
import { type CatalogSource } from "./catalog.js";
|
|
7
|
+
import { GrokBuildCredentialStore } from "./store.js";
|
|
8
|
+
/** One process-local owner of the credential and the account model list. */
|
|
9
|
+
export declare class GrokBuildSession {
|
|
10
|
+
readonly store: GrokBuildCredentialStore;
|
|
11
|
+
readonly models: MutableModels;
|
|
12
|
+
private readonly baselineCatalog;
|
|
13
|
+
private liveIds;
|
|
14
|
+
private liveModels;
|
|
15
|
+
private selectedIds;
|
|
16
|
+
private source;
|
|
17
|
+
private listingError;
|
|
18
|
+
private readonly cacheFile;
|
|
19
|
+
private onCatalogChange;
|
|
20
|
+
constructor(store?: GrokBuildCredentialStore, onCatalogChange?: () => void);
|
|
21
|
+
/** Secret-free listing diagnostic from the last refresh. */
|
|
22
|
+
get catalogError(): string | undefined;
|
|
23
|
+
get catalogSource(): CatalogSource;
|
|
24
|
+
availableModels(): Model<Api>[];
|
|
25
|
+
selectedModelIds(): string[] | undefined;
|
|
26
|
+
visibleModels(): Model<Api>[];
|
|
27
|
+
/** Provider whose id matches the harness route so PiAiAdapter can list models. */
|
|
28
|
+
provider(): Provider;
|
|
29
|
+
loadCachedCatalog(): Promise<void>;
|
|
30
|
+
refreshLiveCatalog(signal?: AbortSignal): Promise<void>;
|
|
31
|
+
setSelectedModels(ids: readonly string[]): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Backdate the stored token's expiry so the next `getAuth()` refreshes.
|
|
34
|
+
* Called after an upstream 401 rejected a locally-valid token.
|
|
35
|
+
*/
|
|
36
|
+
invalidateAccessToken(): Promise<void>;
|
|
37
|
+
logout(): Promise<void>;
|
|
38
|
+
private writeCache;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,EACN,KAAK,aAAa,EAKlB,MAAM,cAAc,CAAC;AAItB,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAsDtD,4EAA4E;AAC5E,qBAAa,gBAAgB;IAC5B,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwB;IACxD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,eAAe,CAA2B;gBAEtC,KAAK,GAAE,wBAAyD,EAAE,eAAe,CAAC,EAAE,MAAM,IAAI;IAW1G,4DAA4D;IAC5D,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAED,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED,eAAe,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE;IAI/B,gBAAgB,IAAI,MAAM,EAAE,GAAG,SAAS;IAIxC,aAAa,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE;IAO7B,kFAAkF;IAClF,QAAQ,IAAI,QAAQ;IASd,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAelC,kBAAkB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBvD,iBAAiB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9D;;;OAGG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAiBf,UAAU;CAaxB"}
|
package/lib/store.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner-only persistent OAuth credential storage for coding-subscription routes.
|
|
3
|
+
* @module dsh-coding-subscription-oauth/store
|
|
4
|
+
*/
|
|
5
|
+
import type { Credential, CredentialInfo, CredentialStore } from "@earendil-works/pi-ai";
|
|
6
|
+
/** Resolve one private OAuth document path beneath DSH_HOME. */
|
|
7
|
+
export declare function oauthCredentialPath(basename: string, dshHome?: string): string;
|
|
8
|
+
/** Resolve the legacy Grok Build OAuth document path. */
|
|
9
|
+
export declare function grokBuildAuthPath(dshHome?: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* File-backed pi-ai store scoped to exactly one provider id. Separate provider
|
|
12
|
+
* files prevent one corrupted or rotated credential from affecting another.
|
|
13
|
+
*/
|
|
14
|
+
export declare class OAuthCredentialFileStore implements CredentialStore {
|
|
15
|
+
readonly providerId: string;
|
|
16
|
+
private readonly label;
|
|
17
|
+
readonly filename: string;
|
|
18
|
+
constructor(providerId: string, filename: string, label: string);
|
|
19
|
+
private readCurrent;
|
|
20
|
+
/**
|
|
21
|
+
* Hardened load. `read`/`list` keep parse failures loud. `modify` treats a
|
|
22
|
+
* safe-but-unparseable document as absent so a confirmed replace can proceed.
|
|
23
|
+
* Unsafe/symlink/wrong-owner/too-large files still throw.
|
|
24
|
+
*/
|
|
25
|
+
private loadCurrent;
|
|
26
|
+
/** Refuse a dest that became unsafe after the lock was taken and before rename. */
|
|
27
|
+
private assertDestinationReplaceable;
|
|
28
|
+
read(providerId: string): Promise<Credential | undefined>;
|
|
29
|
+
list(): Promise<readonly CredentialInfo[]>;
|
|
30
|
+
modify(providerId: string, fn: (current: Credential | undefined) => Promise<Credential | undefined>): Promise<Credential | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Force the next `getAuth()` to refresh by backdating `expires` into the past.
|
|
33
|
+
* Used after an upstream 401: the stored access token was rejected even though
|
|
34
|
+
* the local expiry had not yet passed (server-side revocation or skew). The
|
|
35
|
+
* access/refresh pair is preserved — only the freshness marker moves — so the
|
|
36
|
+
* refresh token can still mint a replacement. Returns true when a credential
|
|
37
|
+
* was actually backdated; false when nothing is stored.
|
|
38
|
+
*/
|
|
39
|
+
invalidate(providerId: string): Promise<boolean>;
|
|
40
|
+
delete(providerId: string): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/** Legacy-named store retained for existing imports and credential migration. */
|
|
43
|
+
export declare class GrokBuildCredentialStore extends OAuthCredentialFileStore {
|
|
44
|
+
constructor(filename?: string);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AAgE1G,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAW9E;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,eAAe;IAI9D,QAAQ,CAAC,UAAU,EAAE,MAAM;IAE3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IALvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGhB,UAAU,EAAE,MAAM,EAC3B,QAAQ,EAAE,MAAM,EACC,KAAK,EAAE,MAAM;YAKjB,WAAW;IAIzB;;;;OAIG;YACW,WAAW;IAmBzB,mFAAmF;YACrE,4BAA4B;IAYpC,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIzD,IAAI,IAAI,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;IAI1C,MAAM,CACX,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,GACtE,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IA0BlC;;;;;;;OAOG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWhD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK/C;AAED,iFAAiF;AACjF,qBAAa,wBAAyB,SAAQ,wBAAwB;gBACzD,QAAQ,GAAE,MAA4B;CAGlD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback + same-origin authorization shared by private plugin Web routes.
|
|
3
|
+
* Rejecting non-loopback Host values closes DNS-rebinding access even when the
|
|
4
|
+
* TCP peer itself is 127.0.0.1 or ::1.
|
|
5
|
+
* @module dsh-coding-subscription-oauth/web-origin
|
|
6
|
+
*/
|
|
7
|
+
import type { IncomingMessage } from "node:http";
|
|
8
|
+
/** Authorize one browser request for owner-local exact/settings routes. */
|
|
9
|
+
export declare function isTrustedLoopbackWebRequest(req: IncomingMessage): boolean;
|
|
10
|
+
//# sourceMappingURL=web-origin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-origin.d.ts","sourceRoot":"","sources":["../../src/web-origin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,2EAA2E;AAC3E,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAezE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic registration helper for plugin-owned Web routes.
|
|
3
|
+
* `webServer.register()` is not fiber-scoped, so a later registration failure
|
|
4
|
+
* must release every earlier route before the setup error escapes.
|
|
5
|
+
* @module dsh-coding-subscription-oauth/web-routes
|
|
6
|
+
*/
|
|
7
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
8
|
+
export interface PluginWebRoute {
|
|
9
|
+
readonly kind: "exact" | "prefix";
|
|
10
|
+
readonly path: string;
|
|
11
|
+
readonly handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface PluginWebRouteRegistry {
|
|
14
|
+
register(route: PluginWebRoute): () => void;
|
|
15
|
+
}
|
|
16
|
+
/** Run imperative route setup or roll every successful registration back. */
|
|
17
|
+
export declare function registerWebRouteSetupAtomically(registry: PluginWebRouteRegistry, setup: (tracked: PluginWebRouteRegistry) => unknown): () => void;
|
|
18
|
+
/** Register all routes or leave the registry exactly as it was. */
|
|
19
|
+
export declare function registerWebRoutesAtomically(registry: PluginWebRouteRegistry, routes: readonly PluginWebRoute[]): () => void;
|
|
20
|
+
//# sourceMappingURL=web-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-routes.d.ts","sourceRoot":"","sources":["../../src/web-routes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtF;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;CAC5C;AAED,6EAA6E;AAC7E,wBAAgB,+BAA+B,CAC9C,QAAQ,EAAE,sBAAsB,EAChC,KAAK,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,GACjD,MAAM,IAAI,CAqBZ;AAED,mEAAmE;AACnE,wBAAgB,2BAA2B,CAC1C,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,SAAS,cAAc,EAAE,GAC/B,MAAM,IAAI,CAcZ"}
|
package/package.json
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-coding-subscription-oauth",
|
|
3
|
+
"description": "DeepSeek Harness coding-subscription OAuth: SuperGrok/Grok Build, ChatGPT Plus Codex, Kimi Code, Claude Code. Fixes AUTH API key is invalid, INVALID_REPLAY_STATE, grok-4.6 xhigh, Kimi Bearer vs x-api-key.",
|
|
4
|
+
"version": "0.5.0",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"registry": "https://registry.npmjs.org/"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/lninghaha/dsh-coding-subscription-oauth.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/lninghaha/dsh-coding-subscription-oauth/issues",
|
|
14
|
+
"homepage": "https://github.com/lninghaha/dsh-coding-subscription-oauth#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"deepseek-harness",
|
|
17
|
+
"dsh-plugin",
|
|
18
|
+
"oauth",
|
|
19
|
+
"grok-build",
|
|
20
|
+
"super-grok",
|
|
21
|
+
"grok-4.6",
|
|
22
|
+
"cli-chat-proxy",
|
|
23
|
+
"openai-codex",
|
|
24
|
+
"chatgpt-plus",
|
|
25
|
+
"kimi-code",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"google-antigravity",
|
|
28
|
+
"xhigh",
|
|
29
|
+
"device-code"
|
|
30
|
+
],
|
|
31
|
+
"type": "module",
|
|
32
|
+
"packageManager": "pnpm@11.21.0",
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
35
|
+
},
|
|
36
|
+
"main": "lib/index.js",
|
|
37
|
+
"types": "lib/index.d.ts",
|
|
38
|
+
"bin": {
|
|
39
|
+
"dsh-coding-oauth": "lib/bin.js",
|
|
40
|
+
"dsh-grok-build": "lib/bin.js"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"clean": "node build/clean.mjs",
|
|
44
|
+
"typecheck": "tsc -b tsconfig.host.json tsconfig.client.json",
|
|
45
|
+
"build:server": "tsc -p tsconfig.build.json && tsc -p tsconfig.dts-bin.json && node build/build-server.mjs",
|
|
46
|
+
"build:client": "node build/build-client.mjs",
|
|
47
|
+
"build:artifacts": "pnpm run clean && pnpm run typecheck && pnpm run build:server && pnpm run build:client",
|
|
48
|
+
"build": "pnpm run release:build",
|
|
49
|
+
"test": "vitest run",
|
|
50
|
+
"test:watch": "vitest",
|
|
51
|
+
"lint": "biome check",
|
|
52
|
+
"check:next": "pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
53
|
+
"check": "pnpm run lint && pnpm run release:build && pnpm run test",
|
|
54
|
+
"release:promote": "node build/promote-release.mjs",
|
|
55
|
+
"release:verify": "node build/verify-release.mjs",
|
|
56
|
+
"release:build": "pnpm run build:artifacts && pnpm run release:promote",
|
|
57
|
+
"release:dry": "node scripts/release.mjs --dry-run",
|
|
58
|
+
"release:pack": "node scripts/release.mjs --pack",
|
|
59
|
+
"verify:deployed": "node scripts/verify-deployed-catalog.mjs",
|
|
60
|
+
"smoke:deployed": "node scripts/smoke-deployed-routes.mjs",
|
|
61
|
+
"prepack": "pnpm run release:build"
|
|
62
|
+
},
|
|
63
|
+
"exports": {
|
|
64
|
+
".": {
|
|
65
|
+
"types": "./lib/index.d.ts",
|
|
66
|
+
"default": "./lib/index.js"
|
|
67
|
+
},
|
|
68
|
+
"./invariant": {
|
|
69
|
+
"types": "./lib/invariant.d.ts",
|
|
70
|
+
"default": "./lib/invariant.js"
|
|
71
|
+
},
|
|
72
|
+
"./client": "./lib/client.js",
|
|
73
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
74
|
+
"./package.json": "./package.json"
|
|
75
|
+
},
|
|
76
|
+
"files": [
|
|
77
|
+
"lib",
|
|
78
|
+
"src",
|
|
79
|
+
"cordis.patch.yml",
|
|
80
|
+
"INSTALL.md",
|
|
81
|
+
"CHANGELOG.md",
|
|
82
|
+
"CONTRIBUTING.md",
|
|
83
|
+
"docs/00-project-rules.md",
|
|
84
|
+
"docs/02-architecture.md",
|
|
85
|
+
"docs/02-architecture.zh-CN.md",
|
|
86
|
+
"README.zh-CN.md",
|
|
87
|
+
"README.ja.md",
|
|
88
|
+
"README.ko.md",
|
|
89
|
+
"README.pt-BR.md",
|
|
90
|
+
"README.es.md",
|
|
91
|
+
"README.fr.md",
|
|
92
|
+
"README.de.md",
|
|
93
|
+
"README.ru.md",
|
|
94
|
+
"patches/dsh-agy@0.1.2.patch",
|
|
95
|
+
"scripts/verify-deployed-catalog.mjs",
|
|
96
|
+
"scripts/smoke-deployed-routes.mjs",
|
|
97
|
+
"scripts/release.mjs",
|
|
98
|
+
"LICENSE",
|
|
99
|
+
"NOTICE"
|
|
100
|
+
],
|
|
101
|
+
"license": "Apache-2.0",
|
|
102
|
+
"dsh": {
|
|
103
|
+
"bundle": {
|
|
104
|
+
"patch": "./cordis.patch.yml"
|
|
105
|
+
},
|
|
106
|
+
"client": {
|
|
107
|
+
"inject": [
|
|
108
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
109
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
110
|
+
"@deepseek-ai/dsh-client-locale"
|
|
111
|
+
],
|
|
112
|
+
"platform": "web"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"dependencies": {
|
|
116
|
+
"undici": "^7.24.8"
|
|
117
|
+
},
|
|
118
|
+
"peerDependencies": {
|
|
119
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
120
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.0-rc.6",
|
|
121
|
+
"@deepseek-ai/dsh-attachment": "*",
|
|
122
|
+
"@deepseek-ai/dsh-credentials": "*",
|
|
123
|
+
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.6",
|
|
124
|
+
"@deepseek-ai/dsh-host-webserver": "*",
|
|
125
|
+
"@deepseek-ai/dsh-invariants": "*",
|
|
126
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6",
|
|
127
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6",
|
|
128
|
+
"@deepseek-ai/dsh-tools": "*",
|
|
129
|
+
"@deepseek-ai/schemastery": "3.18.1",
|
|
130
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
131
|
+
"react": "^18.2.0"
|
|
132
|
+
},
|
|
133
|
+
"peerDependenciesMeta": {
|
|
134
|
+
"@deepseek-ai/cordis": {
|
|
135
|
+
"optional": true
|
|
136
|
+
},
|
|
137
|
+
"@deepseek-ai/dsh-attachment": {
|
|
138
|
+
"optional": true
|
|
139
|
+
},
|
|
140
|
+
"@deepseek-ai/dsh-credentials": {
|
|
141
|
+
"optional": true
|
|
142
|
+
},
|
|
143
|
+
"@deepseek-ai/dsh-host-webserver": {
|
|
144
|
+
"optional": true
|
|
145
|
+
},
|
|
146
|
+
"@deepseek-ai/dsh-invariants": {
|
|
147
|
+
"optional": true
|
|
148
|
+
},
|
|
149
|
+
"@deepseek-ai/dsh-tools": {
|
|
150
|
+
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"react": {
|
|
153
|
+
"optional": true
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"devDependencies": {
|
|
157
|
+
"@biomejs/biome": "^2.5.8",
|
|
158
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
159
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.0-rc.6",
|
|
160
|
+
"@deepseek-ai/dsh-attachment": "0.1.0-rc.6",
|
|
161
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6",
|
|
162
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6",
|
|
163
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.6",
|
|
164
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6",
|
|
165
|
+
"@deepseek-ai/dsh-credentials": "0.1.0-rc.6",
|
|
166
|
+
"@deepseek-ai/dsh-home-paths": "0.1.0-rc.6",
|
|
167
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.0-rc.6",
|
|
168
|
+
"@deepseek-ai/dsh-invariants": "0.1.0-rc.6",
|
|
169
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6",
|
|
170
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.0-rc.6",
|
|
171
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6",
|
|
172
|
+
"@deepseek-ai/schemastery": "3.18.1",
|
|
173
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
174
|
+
"@types/node": "^22.20.0",
|
|
175
|
+
"@types/react": "~18.3.1",
|
|
176
|
+
"esbuild": "^0.28.2",
|
|
177
|
+
"react": "^18.2.0",
|
|
178
|
+
"typescript": "^6.0.3",
|
|
179
|
+
"undici": "^7.24.8",
|
|
180
|
+
"vitest": "^4.1.8"
|
|
181
|
+
},
|
|
182
|
+
"overrides": {
|
|
183
|
+
"@earendil-works/pi-ai": "0.84.2"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
diff --git a/lib/plugin-common-YSDKp1DG.mjs b/lib/plugin-common-YSDKp1DG.mjs
|
|
2
|
+
index 3bd4405d9010705cdbfb675e62538645c4af5321..aeb9dd8375ac4dfc0376b525f44e4cf8eba67719 100644
|
|
3
|
+
--- a/lib/plugin-common-YSDKp1DG.mjs
|
|
4
|
+
+++ b/lib/plugin-common-YSDKp1DG.mjs
|
|
5
|
+
@@ -135,12 +135,17 @@ var AgyAdapter = class extends LlmAdapter {
|
|
6
|
+
providerInfo(_provider) {
|
|
7
|
+
return {
|
|
8
|
+
id: "agy",
|
|
9
|
+
- name: "Antigravity (agy)"
|
|
10
|
+
+ name: "Google Antigravity (OAuth)"
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
async listModels(_provider) {
|
|
14
|
+
- const session = await this.options.getSession();
|
|
15
|
+
- return listAgyModels(session?.auth.access, session?.account.projectId);
|
|
16
|
+
+ try {
|
|
17
|
+
+ const session = await this.options.getSession();
|
|
18
|
+
+ if (!session) return [];
|
|
19
|
+
+ return listAgyModels(session.auth.access, session.account.projectId);
|
|
20
|
+
+ } catch {
|
|
21
|
+
+ return [];
|
|
22
|
+
+ }
|
|
23
|
+
}
|
|
24
|
+
async resolveModel(provider, model) {
|
|
25
|
+
return resolveAgyModel(provider, model);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Local release verifier/packer.
|
|
4
|
+
*
|
|
5
|
+
* This helper never bumps versions, commits, tags, pushes, or publishes. Those
|
|
6
|
+
* operations require an explicit human decision outside this script.
|
|
7
|
+
*/
|
|
8
|
+
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { access, mkdir, readFile, rename, rm } from "node:fs/promises";
|
|
10
|
+
import { dirname, join, resolve } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
+
const output = join(root, "output");
|
|
15
|
+
const knownFlags = new Set(["--dry-run", "--pack", "--help"]);
|
|
16
|
+
const args = new Set(process.argv.slice(2));
|
|
17
|
+
for (const argument of args) {
|
|
18
|
+
if (!knownFlags.has(argument)) {
|
|
19
|
+
console.error(`Unknown option: ${argument}`);
|
|
20
|
+
process.exit(2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (args.has("--dry-run") && args.has("--pack")) {
|
|
24
|
+
console.error("Choose either --dry-run or --pack, not both.");
|
|
25
|
+
process.exit(2);
|
|
26
|
+
}
|
|
27
|
+
if (args.has("--help")) {
|
|
28
|
+
console.log(`dsh-coding-subscription-oauth release helper
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
node scripts/release.mjs --dry-run Verify current release artifacts and packed file list
|
|
32
|
+
node scripts/release.mjs --pack Rebuild, verify, and write a local tarball under output/
|
|
33
|
+
|
|
34
|
+
This command never changes versions, commits, tags, pushes, or publishes.`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const mode = args.has("--pack") ? "pack" : "dry-run";
|
|
39
|
+
const manifest = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
|
|
40
|
+
const changelog = await readFile(join(root, "CHANGELOG.md"), "utf8");
|
|
41
|
+
const readme = await readFile(join(root, "README.md"), "utf8");
|
|
42
|
+
const expectedName = "dsh-coding-subscription-oauth";
|
|
43
|
+
const semver = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/u;
|
|
44
|
+
|
|
45
|
+
function fail(message) {
|
|
46
|
+
throw new Error(message);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function run(command, commandArgs, options = {}) {
|
|
50
|
+
const result = spawnSync(command, commandArgs, {
|
|
51
|
+
cwd: root,
|
|
52
|
+
encoding: "utf8",
|
|
53
|
+
stdio: options.capture === true ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
54
|
+
});
|
|
55
|
+
if (result.error !== undefined) throw result.error;
|
|
56
|
+
if (result.status !== 0) {
|
|
57
|
+
const details = options.capture === true ? `${result.stderr ?? ""}${result.stdout ?? ""}`.trim() : "";
|
|
58
|
+
fail(`${command} ${commandArgs.join(" ")} failed${details === "" ? "" : `:\n${details}`}`);
|
|
59
|
+
}
|
|
60
|
+
return result.stdout ?? "";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (manifest.name !== expectedName) fail(`package name must be ${expectedName}; found ${String(manifest.name)}`);
|
|
64
|
+
if (typeof manifest.version !== "string" || !semver.test(manifest.version)) {
|
|
65
|
+
fail(`package version is not valid semver: ${String(manifest.version)}`);
|
|
66
|
+
}
|
|
67
|
+
if (manifest.private === true) fail("release package must not be private");
|
|
68
|
+
|
|
69
|
+
const releaseVersions = [
|
|
70
|
+
...changelog.matchAll(/^##\s+v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)(?:\s+-\s+\d{4}-\d{2}-\d{2})?\s*$/gmu),
|
|
71
|
+
].map((match) => match[1]);
|
|
72
|
+
if (releaseVersions[0] !== manifest.version) {
|
|
73
|
+
fail(`top CHANGELOG release (${releaseVersions[0] ?? "missing"}) does not match package version ${manifest.version}`);
|
|
74
|
+
}
|
|
75
|
+
if (!readme.includes(manifest.version)) fail(`README.md does not mention ${manifest.version}`);
|
|
76
|
+
|
|
77
|
+
if (mode === "pack") run("pnpm", ["run", "release:build"]);
|
|
78
|
+
else run("pnpm", ["run", "release:verify"]);
|
|
79
|
+
|
|
80
|
+
const packOutput = run("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], { capture: true });
|
|
81
|
+
let packReport;
|
|
82
|
+
try {
|
|
83
|
+
packReport = JSON.parse(packOutput);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
throw new Error("npm pack --dry-run returned invalid JSON", { cause: error });
|
|
86
|
+
}
|
|
87
|
+
const report = Array.isArray(packReport) ? packReport[0] : undefined;
|
|
88
|
+
if (report === undefined || !Array.isArray(report.files)) fail("npm pack did not return a file manifest");
|
|
89
|
+
const packedFiles = report.files.map((entry) => entry.path).sort();
|
|
90
|
+
const packed = new Set(packedFiles);
|
|
91
|
+
const missingModes = report.files.filter((entry) => typeof entry.mode !== "number").map((entry) => entry.path);
|
|
92
|
+
if (missingModes.length > 0) fail(`npm pack omitted file modes:\n${missingModes.sort().join("\n")}`);
|
|
93
|
+
const privateModes = report.files
|
|
94
|
+
.filter((entry) => typeof entry.mode === "number" && (entry.mode & 0o044) !== 0o044)
|
|
95
|
+
.map((entry) => `${entry.path} (${entry.mode.toString(8)})`)
|
|
96
|
+
.sort();
|
|
97
|
+
if (privateModes.length > 0)
|
|
98
|
+
fail(`packed release contains files unreadable outside their owner:\n${privateModes.join("\n")}`);
|
|
99
|
+
const writableModes = report.files
|
|
100
|
+
.filter((entry) => typeof entry.mode === "number" && (entry.mode & 0o022) !== 0)
|
|
101
|
+
.map((entry) => `${entry.path} (${entry.mode.toString(8)})`)
|
|
102
|
+
.sort();
|
|
103
|
+
if (writableModes.length > 0) fail(`packed release contains group/world-writable files:\n${writableModes.join("\n")}`);
|
|
104
|
+
for (const required of [
|
|
105
|
+
"package.json",
|
|
106
|
+
"README.md",
|
|
107
|
+
"LICENSE",
|
|
108
|
+
"cordis.patch.yml",
|
|
109
|
+
"lib/index.js",
|
|
110
|
+
"lib/index.d.ts",
|
|
111
|
+
"lib/client.js",
|
|
112
|
+
"lib/bin.js",
|
|
113
|
+
"lib/invariant.js",
|
|
114
|
+
]) {
|
|
115
|
+
if (!packed.has(required)) fail(`packed release is missing ${required}`);
|
|
116
|
+
}
|
|
117
|
+
const packedBin = report.files.find((entry) => entry.path === "lib/bin.js");
|
|
118
|
+
if (typeof packedBin?.mode === "number" && (packedBin.mode & 0o111) === 0) {
|
|
119
|
+
fail(`packed CLI is not executable: lib/bin.js (${packedBin.mode.toString(8)})`);
|
|
120
|
+
}
|
|
121
|
+
const forbiddenFragments = [
|
|
122
|
+
"docs/local",
|
|
123
|
+
"reference/",
|
|
124
|
+
".env",
|
|
125
|
+
".secrets",
|
|
126
|
+
"package-lock.json",
|
|
127
|
+
"tsdown.config",
|
|
128
|
+
"lib/client.cjs",
|
|
129
|
+
"docs/MIGRATION.md",
|
|
130
|
+
];
|
|
131
|
+
const leaked = packedFiles.filter((path) => forbiddenFragments.some((fragment) => path.includes(fragment)));
|
|
132
|
+
if (leaked.length > 0) fail(`packed release contains forbidden files:\n${leaked.join("\n")}`);
|
|
133
|
+
|
|
134
|
+
console.log(`Verified ${manifest.name}@${manifest.version}`);
|
|
135
|
+
console.log(`Packed files: ${packedFiles.length}`);
|
|
136
|
+
|
|
137
|
+
if (mode === "dry-run") {
|
|
138
|
+
console.log("Dry-run complete. No version, Git, registry, or tarball changes were made.");
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const staging = join(output, `.pack-${process.pid}`);
|
|
143
|
+
await rm(staging, { recursive: true, force: true });
|
|
144
|
+
await mkdir(staging, { recursive: true });
|
|
145
|
+
try {
|
|
146
|
+
const actualOutput = run("npm", ["pack", "--json", "--ignore-scripts", "--pack-destination", staging], {
|
|
147
|
+
capture: true,
|
|
148
|
+
});
|
|
149
|
+
let actualReport;
|
|
150
|
+
try {
|
|
151
|
+
actualReport = JSON.parse(actualOutput);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
throw new Error("npm pack returned invalid JSON", { cause: error });
|
|
154
|
+
}
|
|
155
|
+
const filename = Array.isArray(actualReport) ? actualReport[0]?.filename : undefined;
|
|
156
|
+
if (typeof filename !== "string" || filename.length === 0) fail("npm pack did not report a tarball filename");
|
|
157
|
+
const source = join(staging, filename);
|
|
158
|
+
await access(source);
|
|
159
|
+
await mkdir(output, { recursive: true });
|
|
160
|
+
const target = join(output, `${manifest.name}-${manifest.version}.tgz`);
|
|
161
|
+
await rm(target, { force: true });
|
|
162
|
+
await rename(source, target);
|
|
163
|
+
console.log(`Wrote ${target}`);
|
|
164
|
+
} finally {
|
|
165
|
+
await rm(staging, { recursive: true, force: true });
|
|
166
|
+
}
|