feat: add clientConfig() method for querying client metadata

hookUrl/hookToken are now resolved via /auth/skill-credit/client-config
endpoint instead of key binding. Added ClientConfig type and extraHeaders
support in requestApi.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ywkj 2026-03-19 07:37:56 +08:00
parent 69051a3479
commit b05363e8f0
16 changed files with 72 additions and 15 deletions

6
dist/client.d.ts vendored
View File

@ -1,4 +1,4 @@
import type { ApiResponse, SessionResponse } from './types.js';
import type { ApiResponse, ClientConfig, SessionResponse } from './types.js';
export interface SkillClientOptions {
/** Override AUTH_BASE (gateway URL for token acquisition) */
authBase?: string;
@ -18,8 +18,10 @@ export declare class SkillClient {
private readonly apiBase;
private readonly dryRun;
constructor(options?: SkillClientOptions);
/** Fetch raw session info (token + hookUrl + hookToken + expiresIn) */
/** Fetch raw session info (token + expiresIn) */
session(): Promise<SessionResponse>;
/** Fetch client config (metadata with hook info, provider keys, etc.) */
clientConfig(): Promise<ClientConfig>;
get(path: string): Promise<ApiResponse>;
post(path: string, body?: unknown): Promise<ApiResponse>;
put(path: string, body?: unknown): Promise<ApiResponse>;

View File

@ -1 +1 @@
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAyB,eAAe,EAAE,MAAM,YAAY,CAAC;AAatF,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,OAAO,GAAE,kBAAuB;IAU5C,uEAAuE;IACjE,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAOnC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;YAMlD,OAAO;YAoBP,QAAQ;YAUR,YAAY;YASZ,YAAY;CAmB3B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAE3E"}
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAyB,eAAe,EAAE,MAAM,YAAY,CAAC;AAapG,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,OAAO,GAAE,kBAAuB;IAU5C,iDAAiD;IAC3C,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAOzC,yEAAyE;IACnE,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;IAoBrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;YAMlD,OAAO;YAoBP,QAAQ;YAUR,YAAY;YASZ,YAAY;CAmB3B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAE3E"}

13
dist/client.js vendored
View File

@ -36,13 +36,24 @@ export class SkillClient {
throw new Error('CLIENT_KEY is required. Set via env or pass clientKey option.');
}
}
/** Fetch raw session info (token + hookUrl + hookToken + expiresIn) */
/** Fetch raw session info (token + expiresIn) */
async session() {
if (this.dryRun) {
return { accessToken: '<dry-run-token>', expiresIn: 900 };
}
return this.fetchSession();
}
/** Fetch client config (metadata with hook info, provider keys, etc.) */
async clientConfig() {
if (this.dryRun) {
return { clientId: '<dry-run>', name: '<dry-run>', status: 'active', metadata: {} };
}
const result = await requestApi('GET', `${this.config.authBase}/auth/skill-credit/client-config`, undefined, undefined, { 'X-Client-Key': this.config.clientKey });
if (result.status < 200 || result.status >= 300) {
throw new Error(`Client config failed: HTTP ${result.status}${result.body}`);
}
return JSON.parse(result.body);
}
async get(path) {
return this.request('GET', path);
}

2
dist/client.js.map vendored

File diff suppressed because one or more lines are too long

2
dist/http.d.ts vendored
View File

@ -2,5 +2,5 @@ import type { ApiResponse, HttpMethod } from './types.js';
/**
* Make HTTP request to API
*/
export declare function requestApi(method: HttpMethod, url: string, authToken?: string, body?: string): Promise<ApiResponse>;
export declare function requestApi(method: HttpMethod, url: string, authToken?: string, body?: string, extraHeaders?: Record<string, string>): Promise<ApiResponse>;
//# sourceMappingURL=http.d.ts.map

2
dist/http.d.ts.map vendored
View File

@ -1 +1 @@
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,WAAW,CAAC,CAyBtB"}
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,OAAO,CAAC,WAAW,CAAC,CA0BtB"}

3
dist/http.js vendored
View File

@ -1,9 +1,10 @@
/**
* Make HTTP request to API
*/
export async function requestApi(method, url, authToken, body) {
export async function requestApi(method, url, authToken, body, extraHeaders) {
const headers = {
'Content-Type': 'application/json',
...extraHeaders,
};
if (authToken) {
headers['Authorization'] = `Bearer ${authToken}`;

2
dist/http.js.map vendored
View File

@ -1 +1 @@
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAkB,EAClB,GAAW,EACX,SAAkB,EAClB,IAAa;IAEb,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,SAAS,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAgB;QAC3B,MAAM;QACN,OAAO;KACR,CAAC;IAEF,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAE3C,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI,EAAE,YAAY;KACnB,CAAC;AACJ,CAAC"}
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAkB,EAClB,GAAW,EACX,SAAkB,EAClB,IAAa,EACb,YAAqC;IAErC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,YAAY;KAChB,CAAC;IAEF,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,SAAS,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAgB;QAC3B,MAAM;QACN,OAAO;KACR,CAAC;IAEF,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAE3C,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI,EAAE,YAAY;KACnB,CAAC;AACJ,CAAC"}

2
dist/index.d.ts vendored
View File

@ -11,5 +11,5 @@
*/
export { createSkillClient, SkillClient } from './client.js';
export type { SkillClientOptions } from './client.js';
export type { EnvConfig, SessionResponse, CachedTokenData, ApiResponse, HttpMethod, } from './types.js';
export type { EnvConfig, SessionResponse, ClientConfig, CachedTokenData, ApiResponse, HttpMethod, } from './types.js';
//# sourceMappingURL=index.d.ts.map

2
dist/index.d.ts.map vendored
View File

@ -1 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,YAAY,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,YAAY,EACV,SAAS,EACT,eAAe,EACf,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,GACX,MAAM,YAAY,CAAC"}

9
dist/types.d.ts vendored
View File

@ -21,6 +21,15 @@ export interface SessionResponse {
hookToken?: string;
expiresIn: number;
}
/**
* Client config from /auth/skill-credit/client-config
*/
export interface ClientConfig {
clientId: string;
name: string;
status: string;
metadata: Record<string, unknown>;
}
/**
* Cached token data stored on disk
*/

2
dist/types.d.ts.map vendored
View File

@ -1 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}

View File

@ -1,4 +1,4 @@
import type { ApiResponse, EnvConfig, HttpMethod, SessionResponse } from './types.js';
import type { ApiResponse, ClientConfig, EnvConfig, HttpMethod, SessionResponse } from './types.js';
import { requestApi } from './http.js';
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
@ -57,7 +57,7 @@ export class SkillClient {
}
}
/** Fetch raw session info (token + hookUrl + hookToken + expiresIn) */
/** Fetch raw session info (token + expiresIn) */
async session(): Promise<SessionResponse> {
if (this.dryRun) {
return { accessToken: '<dry-run-token>', expiresIn: 900 };
@ -65,6 +65,27 @@ export class SkillClient {
return this.fetchSession();
}
/** Fetch client config (metadata with hook info, provider keys, etc.) */
async clientConfig(): Promise<ClientConfig> {
if (this.dryRun) {
return { clientId: '<dry-run>', name: '<dry-run>', status: 'active', metadata: {} };
}
const result = await requestApi(
'GET',
`${this.config.authBase}/auth/skill-credit/client-config`,
undefined,
undefined,
{ 'X-Client-Key': this.config.clientKey },
);
if (result.status < 200 || result.status >= 300) {
throw new Error(`Client config failed: HTTP ${result.status}${result.body}`);
}
return JSON.parse(result.body) as ClientConfig;
}
async get(path: string): Promise<ApiResponse> {
return this.request('GET', path);
}

View File

@ -7,10 +7,12 @@ export async function requestApi(
method: HttpMethod,
url: string,
authToken?: string,
body?: string
body?: string,
extraHeaders?: Record<string, string>,
): Promise<ApiResponse> {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
...extraHeaders,
};
if (authToken) {

View File

@ -18,6 +18,7 @@ export type { SkillClientOptions } from './client.js';
export type {
EnvConfig,
SessionResponse,
ClientConfig,
CachedTokenData,
ApiResponse,
HttpMethod,

View File

@ -23,6 +23,16 @@ export interface SessionResponse {
expiresIn: number;
}
/**
* Client config from /auth/skill-credit/client-config
*/
export interface ClientConfig {
clientId: string;
name: string;
status: string;
metadata: Record<string, unknown>;
}
/**
* Cached token data stored on disk
*/