From be8c78cabfedfad21a80521082de0f63acd5e939 Mon Sep 17 00:00:00 2001 From: fishdivinity Date: Tue, 27 Oct 2026 15:05:57 +0800 Subject: [PATCH 1/5] feat(config): add a token field the Plugins page can edit DSH 0.2.1 serves a settings namespace only for a plugin whose Config carries at least one volatile() field. dsh-github had none, so the settings service skipped the whole namespace and the GitHub row had no editable form at all. githubToken is now that field. tokenSource also gains a config member that auto tries before the credentials file, the environment and the gh CLI, so a token saved on the page is what the host resolves. A volatile field hands the plugin a live reference instead of the stored string, and a Settings write updates that reference in place. liveValue() reads it on every operation, which is also what makes a saved token apply without reloading the plugin. Refs #29 --- lib/config.d.ts | 21 +++++++++++++++++++- lib/config.d.ts.map | 2 +- lib/config.js | 34 +++++++++++++++++++++++++++++-- lib/config.js.map | 2 +- lib/credential.d.ts | 8 +++++--- lib/credential.d.ts.map | 2 +- lib/credential.js | 28 ++++++++++++++++++-------- lib/credential.js.map | 2 +- lib/state.d.ts.map | 2 +- lib/state.js | 4 ++-- lib/state.js.map | 2 +- src/config.ts | 44 ++++++++++++++++++++++++++++++++++++++--- src/credential.ts | 26 +++++++++++++++++------- src/state.ts | 4 ++-- 14 files changed, 147 insertions(+), 34 deletions(-) diff --git a/lib/config.d.ts b/lib/config.d.ts index 97b9de8..ff57950 100644 --- a/lib/config.d.ts +++ b/lib/config.d.ts @@ -11,7 +11,7 @@ import z from '@deepseek-ai/schemastery'; /** GitHub write actions the plugin may perform (each still requires approval). */ export type GithubAction = 'pr.create' | 'review.post' | 'issue.create' | 'issue.comment' | 'issue.close' | 'pr.merge' | 'pr.update' | 'ci.run'; /** Where a GitHub token is looked up. `auto` tries them in order. */ -export type TokenSource = 'auto' | 'credentials' | 'env' | 'gh'; +export type TokenSource = 'auto' | 'config' | 'credentials' | 'env' | 'gh'; /** * The CI surface: the one-shot `ci_run` tool, the polling review bot, the * `/ci` command family, and the status-check gate. Every tunable is a Schema @@ -68,6 +68,12 @@ export interface Config { tokenSource: TokenSource; /** Credentials-seam reference / environment-variable name for the token. */ tokenRef: string; + /** + * Token typed into the Plugins page configuration form. It sits in the profile + * configuration as plain text, which is what the credentials file is too; + * leave it empty when the configuration is shared with other tools. + */ + githubToken: string; /** `owner/repo` used when a call does not name one and git has no origin. */ defaultOwnerRepo?: string; /** Whether `/pr create` may instruct the model to commit and push first. */ @@ -120,5 +126,18 @@ export declare const DEFAULT_CODE_EXTENSIONS: string[]; /** Default test-path globs for the test-existence rule. */ export declare const DEFAULT_TEST_PATTERNS: string[]; export declare const CiConfig: z; +/** + * Read one configuration value a volatile field hands over as a live reference. + * + * Such a field arrives as an object carrying `get()` instead of the stored + * value, and a Settings write updates that object in place — reading it per + * operation is what lets a token saved on the page apply without reloading the + * plugin. + * @param value - plain value or live reference. + * @returns the current value. + */ +export declare function liveValue(value: T | { + get(): T; +}): T; export declare const Config: z; //# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/lib/config.d.ts.map b/lib/config.d.ts.map index 56d7535..e98994f 100644 --- a/lib/config.d.ts.map +++ b/lib/config.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/config.js b/lib/config.js index 7628aa4..ba6bb18 100644 --- a/lib/config.js +++ b/lib/config.js @@ -68,14 +68,44 @@ export const CiConfig = z.object({ reportDir: z.string().default('') .description('Report-file directory; defaults to DSH_GITHUB_CI_OUTPUT_DIR, then the workspace directory.'), }); +/** + * A string field the Plugins page may edit. + * + * `.volatile()` is what makes the field reachable from the browser at all: DSH + * serves a settings namespace only when its Config exposes at least one + * volatile field, and accepts a write only beneath a volatile node. A volatile + * schema types its output as `Volatile` because the plugin receives a + * live reference rather than the stored value; {@link liveValue} reads that + * reference, so the schema keeps the plain face its consumers use. + * @param description - schema description the settings form shows. + * @returns the schema field. + */ +function editableString(description) { + return z.string().default('').volatile().description(description); +} +/** + * Read one configuration value a volatile field hands over as a live reference. + * + * Such a field arrives as an object carrying `get()` instead of the stored + * value, and a Settings write updates that object in place — reading it per + * operation is what lets a token saved on the page apply without reloading the + * plugin. + * @param value - plain value or live reference. + * @returns the current value. + */ +export function liveValue(value) { + const getter = value.get; + return typeof getter === 'function' ? value.get() : value; +} export const Config = z.object({ - tokenSource: z.union(['auto', 'credentials', 'env', 'gh']) + tokenSource: z.union(['auto', 'config', 'credentials', 'env', 'gh']) .default('auto') - .description('Token lookup source: auto tries credentials → env → gh in order.'), + .description('Token lookup source: auto tries this page → credentials → env → gh in order.'), tokenRef: z.string() .pattern(/^[A-Za-z_][A-Za-z0-9_]*$/) .default('GITHUB_TOKEN') .description('Credential reference / environment variable name holding the token.'), + githubToken: editableString('Token set from this page; used before the credentials file when non-empty. Stored in the profile configuration in plain text.'), defaultOwnerRepo: z.string() .pattern(OWNER_REPO_PATTERN) .description('Fallback owner/repo when neither the call nor git names one.'), diff --git a/lib/config.js.map b/lib/config.js.map index 4a1c14e..d291022 100644 --- a/lib/config.js.map +++ b/lib/config.js.map @@ -1 +1 @@ -{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/credential.d.ts b/lib/credential.d.ts index d27923c..fddda79 100644 --- a/lib/credential.d.ts +++ b/lib/credential.d.ts @@ -29,14 +29,16 @@ export declare function runGhCli(args: string[], signal?: AbortSignal): Promise< /** * Resolve the GitHub token for one operation. * - * `auto` order: credentials seam → `GITHUB_TOKEN`-style environment variable → - * `gh` CLI logged-in token. An explicit source restricts to that one source. + * `auto` order: configuration field set on the plugin's page → credentials seam + * → `GITHUB_TOKEN`-style environment variable → `gh` CLI logged-in token. An + * explicit source restricts to that one source. * @param credentials - the credentials seam (`ctx.credentials`). * @param tokenSource - configured lookup policy. * @param tokenRef - reference / environment-variable name. * @param runGh - `gh` CLI runner; the real one by default. * @param signal - aborts the `gh` lookup. + * @param configuredToken - token typed into the Plugins page configuration form. * @returns the token with its source, or a structured error with guidance. */ -export declare function resolveToken(credentials: CredentialProvider, tokenSource: TokenSource, tokenRef: string, runGh?: GhRunner, signal?: AbortSignal): Promise; +export declare function resolveToken(credentials: CredentialProvider, tokenSource: TokenSource, tokenRef: string, runGh?: GhRunner, signal?: AbortSignal, configuredToken?: string): Promise; //# sourceMappingURL=credential.d.ts.map \ No newline at end of file diff --git a/lib/credential.d.ts.map b/lib/credential.d.ts.map index 7934595..a931a7f 100644 --- a/lib/credential.d.ts.map +++ b/lib/credential.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;CACrC;AAED,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAE7G,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAO5F,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,kBAAkB,EAC/B,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,QAAmB,EAC1B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,CAsC1B"} \ No newline at end of file +{"version":3,"file":"credential.d.ts","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AAEtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,wEAAwE;AACxE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;CACrC;AAED,iEAAiE;AACjE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAE7G,0DAA0D;AAC1D,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAQ5F,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,kBAAkB,EAC/B,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,QAAmB,EAC1B,MAAM,CAAC,EAAE,WAAW,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,eAAe,CAAC,CA8C1B"} \ No newline at end of file diff --git a/lib/credential.js b/lib/credential.js index 353e1c0..48d0d4b 100644 --- a/lib/credential.js +++ b/lib/credential.js @@ -10,9 +10,10 @@ */ import { credentialRef } from '@deepseek-ai/dsh-credentials'; import { execFile } from 'node:child_process'; -const NO_TOKEN_GUIDANCE = 'Configure one of: 1) a dsh credential for this reference (recommended; ' + - '$DSH_HOME/.credentials.yaml), 2) the same-named environment variable, or ' + - '3) `gh auth login` for the gh CLI. Set `tokenSource` in cordis.yml to pin one source.'; +const NO_TOKEN_GUIDANCE = 'Configure one of: 1) the GitHub token field on this plugin\'s page in the Plugins panel, ' + + '2) a dsh credential for this reference (' + + '$DSH_HOME/.credentials.yaml), 3) the same-named environment variable, or ' + + '4) `gh auth login` for the gh CLI. Set `tokenSource` in cordis.yml to pin one source.'; /** Run the real `gh` CLI with stdout captured (never logged). */ export function runGhCli(args, signal) { return new Promise((resolve, reject) => { @@ -27,18 +28,29 @@ export function runGhCli(args, signal) { /** * Resolve the GitHub token for one operation. * - * `auto` order: credentials seam → `GITHUB_TOKEN`-style environment variable → - * `gh` CLI logged-in token. An explicit source restricts to that one source. + * `auto` order: configuration field set on the plugin's page → credentials seam + * → `GITHUB_TOKEN`-style environment variable → `gh` CLI logged-in token. An + * explicit source restricts to that one source. * @param credentials - the credentials seam (`ctx.credentials`). * @param tokenSource - configured lookup policy. * @param tokenRef - reference / environment-variable name. * @param runGh - `gh` CLI runner; the real one by default. * @param signal - aborts the `gh` lookup. + * @param configuredToken - token typed into the Plugins page configuration form. * @returns the token with its source, or a structured error with guidance. */ -export async function resolveToken(credentials, tokenSource, tokenRef, runGh = runGhCli, signal) { - const order = tokenSource === 'auto' ? ['credentials', 'env', 'gh'] : [tokenSource]; +export async function resolveToken(credentials, tokenSource, tokenRef, runGh = runGhCli, signal, configuredToken) { + const typed = configuredToken?.trim(); + const configured = typed === undefined || typed === '' ? undefined : typed; + const order = tokenSource === 'auto' + ? [...(configured === undefined ? [] : ['config']), 'credentials', 'env', 'gh'] + : [tokenSource]; for (const source of order) { + if (source === 'config') { + if (configured !== undefined) + return { ok: true, token: { value: configured, source: 'config' } }; + continue; + } if (source === 'credentials') { let ref; try { @@ -72,7 +84,7 @@ export async function resolveToken(credentials, tokenSource, tokenRef, runGh = r ok: false, error: { code: 'no-token', - message: `no GitHub token found (source: ${tokenSource === 'auto' ? 'credentials/env/gh' : tokenSource})`, + message: `no GitHub token found (source: ${tokenSource === 'auto' ? 'config/credentials/env/gh' : tokenSource})`, guidance: NO_TOKEN_GUIDANCE, }, }; diff --git a/lib/credential.js.map b/lib/credential.js.map index 77876b4..d8d352a 100644 --- a/lib/credential.js.map +++ b/lib/credential.js.map @@ -1 +1 @@ -{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"credential.js","sourceRoot":"","sources":["../src/credential.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/state.d.ts.map b/lib/state.d.ts.map index 2158479..2c5ea76 100644 --- a/lib/state.d.ts.map +++ b/lib/state.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/state.js b/lib/state.js index 34d5ad5..be2eb13 100644 --- a/lib/state.js +++ b/lib/state.js @@ -1,7 +1,7 @@ import { GithubClient, GithubGraphqlClient, clientOptionsFromConfig } from "./github.js"; import { repoFromRemoteUrl } from "./git.js"; import { resolveToken } from "./credential.js"; -import { CiConfig } from "./config.js"; +import { CiConfig, liveValue } from "./config.js"; const REPO_GUIDANCE = 'Name the repository with the ownerRepo parameter, set defaultOwnerRepo in cordis.yml, or run inside a checkout with a GitHub origin remote.'; const REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/; /** @@ -30,7 +30,7 @@ export function createState(ctx, config, runGit, runGh, fetchImpl) { workspaceDir: normalizedConfig.workspaceDir ?? process.cwd(), apiHost, isCiDriver: process.env.DSH_GITHUB_CI_DRIVER === '1', - resolveToken: (signal) => resolveToken(ctx.credentials, normalizedConfig.tokenSource, normalizedConfig.tokenRef, runGh, signal), + resolveToken: (signal) => resolveToken(ctx.credentials, normalizedConfig.tokenSource, normalizedConfig.tokenRef, runGh, signal, liveValue(normalizedConfig.githubToken)), client: (token) => new GithubClient(token, clientOptions), graphqlClient: (token) => new GithubGraphqlClient(token, clientOptions), resolveRepo: (ownerRepo, signal) => resolveRepo(state, ownerRepo, signal), diff --git a/lib/state.js.map b/lib/state.js.map index 18c6092..c7b5a13 100644 --- a/lib/state.js.map +++ b/lib/state.js.map @@ -1 +1 @@ -{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 242c00b..708495b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -13,7 +13,7 @@ import z from '@deepseek-ai/schemastery' export type GithubAction = 'pr.create' | 'review.post' | 'issue.create' | 'issue.comment' | 'issue.close' | 'pr.merge' | 'pr.update' | 'ci.run' /** Where a GitHub token is looked up. `auto` tries them in order. */ -export type TokenSource = 'auto' | 'credentials' | 'env' | 'gh' +export type TokenSource = 'auto' | 'config' | 'credentials' | 'env' | 'gh' /** * The CI surface: the one-shot `ci_run` tool, the polling review bot, the @@ -72,6 +72,12 @@ export interface Config { tokenSource: TokenSource /** Credentials-seam reference / environment-variable name for the token. */ tokenRef: string + /** + * Token typed into the Plugins page configuration form. It sits in the profile + * configuration as plain text, which is what the credentials file is too; + * leave it empty when the configuration is shared with other tools. + */ + githubToken: string /** `owner/repo` used when a call does not name one and git has no origin. */ defaultOwnerRepo?: string /** Whether `/pr create` may instruct the model to commit and push first. */ @@ -184,14 +190,46 @@ export const CiConfig: z = z.object({ .description('Report-file directory; defaults to DSH_GITHUB_CI_OUTPUT_DIR, then the workspace directory.'), }) +/** + * A string field the Plugins page may edit. + * + * `.volatile()` is what makes the field reachable from the browser at all: DSH + * serves a settings namespace only when its Config exposes at least one + * volatile field, and accepts a write only beneath a volatile node. A volatile + * schema types its output as `Volatile` because the plugin receives a + * live reference rather than the stored value; {@link liveValue} reads that + * reference, so the schema keeps the plain face its consumers use. + * @param description - schema description the settings form shows. + * @returns the schema field. + */ +function editableString(description: string): z { + return z.string().default('').volatile().description(description) as unknown as z +} + +/** + * Read one configuration value a volatile field hands over as a live reference. + * + * Such a field arrives as an object carrying `get()` instead of the stored + * value, and a Settings write updates that object in place — reading it per + * operation is what lets a token saved on the page apply without reloading the + * plugin. + * @param value - plain value or live reference. + * @returns the current value. + */ +export function liveValue(value: T | { get(): T }): T { + const getter = (value as { get?: unknown }).get + return typeof getter === 'function' ? (value as { get(): T }).get() : (value as T) +} + export const Config: z = z.object({ - tokenSource: z.union(['auto', 'credentials', 'env', 'gh'] as const) + tokenSource: z.union(['auto', 'config', 'credentials', 'env', 'gh'] as const) .default('auto') - .description('Token lookup source: auto tries credentials → env → gh in order.'), + .description('Token lookup source: auto tries this page → credentials → env → gh in order.'), tokenRef: z.string() .pattern(/^[A-Za-z_][A-Za-z0-9_]*$/) .default('GITHUB_TOKEN') .description('Credential reference / environment variable name holding the token.'), + githubToken: editableString('Token set from this page; used before the credentials file when non-empty. Stored in the profile configuration in plain text.'), defaultOwnerRepo: z.string() .pattern(OWNER_REPO_PATTERN) .description('Fallback owner/repo when neither the call nor git names one.'), diff --git a/src/credential.ts b/src/credential.ts index edbf6c1..68f95d1 100644 --- a/src/credential.ts +++ b/src/credential.ts @@ -32,9 +32,10 @@ export type TokenResolution = { ok: true; token: ResolvedToken } | { ok: false; export type GhRunner = (args: string[], signal?: AbortSignal) => Promise<{ stdout: string }> const NO_TOKEN_GUIDANCE = - 'Configure one of: 1) a dsh credential for this reference (recommended; ' + - '$DSH_HOME/.credentials.yaml), 2) the same-named environment variable, or ' + - '3) `gh auth login` for the gh CLI. Set `tokenSource` in cordis.yml to pin one source.' + 'Configure one of: 1) the GitHub token field on this plugin\'s page in the Plugins panel, ' + + '2) a dsh credential for this reference (' + + '$DSH_HOME/.credentials.yaml), 3) the same-named environment variable, or ' + + '4) `gh auth login` for the gh CLI. Set `tokenSource` in cordis.yml to pin one source.' /** Run the real `gh` CLI with stdout captured (never logged). */ export function runGhCli(args: string[], signal?: AbortSignal): Promise<{ stdout: string }> { @@ -49,13 +50,15 @@ export function runGhCli(args: string[], signal?: AbortSignal): Promise<{ stdout /** * Resolve the GitHub token for one operation. * - * `auto` order: credentials seam → `GITHUB_TOKEN`-style environment variable → - * `gh` CLI logged-in token. An explicit source restricts to that one source. + * `auto` order: configuration field set on the plugin's page → credentials seam + * → `GITHUB_TOKEN`-style environment variable → `gh` CLI logged-in token. An + * explicit source restricts to that one source. * @param credentials - the credentials seam (`ctx.credentials`). * @param tokenSource - configured lookup policy. * @param tokenRef - reference / environment-variable name. * @param runGh - `gh` CLI runner; the real one by default. * @param signal - aborts the `gh` lookup. + * @param configuredToken - token typed into the Plugins page configuration form. * @returns the token with its source, or a structured error with guidance. */ export async function resolveToken( @@ -64,11 +67,20 @@ export async function resolveToken( tokenRef: string, runGh: GhRunner = runGhCli, signal?: AbortSignal, + configuredToken?: string, ): Promise { + const typed = configuredToken?.trim() + const configured = typed === undefined || typed === '' ? undefined : typed const order: Array> = - tokenSource === 'auto' ? ['credentials', 'env', 'gh'] : [tokenSource] + tokenSource === 'auto' + ? [...(configured === undefined ? [] : (['config'] as const)), 'credentials', 'env', 'gh'] + : [tokenSource] for (const source of order) { + if (source === 'config') { + if (configured !== undefined) return { ok: true, token: { value: configured, source: 'config' } } + continue + } if (source === 'credentials') { let ref: ReturnType try { @@ -98,7 +110,7 @@ export async function resolveToken( ok: false, error: { code: 'no-token', - message: `no GitHub token found (source: ${tokenSource === 'auto' ? 'credentials/env/gh' : tokenSource})`, + message: `no GitHub token found (source: ${tokenSource === 'auto' ? 'config/credentials/env/gh' : tokenSource})`, guidance: NO_TOKEN_GUIDANCE, }, } diff --git a/src/state.ts b/src/state.ts index 219754d..03743cd 100644 --- a/src/state.ts +++ b/src/state.ts @@ -14,7 +14,7 @@ import { repoFromRemoteUrl, type GitRunner } from './git.ts' import { resolveToken, type GhRunner, type TokenResolution } from './credential.ts' import type { SubagentsService } from './types.ts' import type { ReviewReport } from './review.ts' -import { CiConfig, type Config } from './config.ts' +import { CiConfig, liveValue, type Config } from './config.ts' /** Result of resolving which repository a call targets. */ export type RepoResolution = { ok: true; repo: string } | { ok: false; code: string; message: string; guidance: string } @@ -101,7 +101,7 @@ export function createState(ctx: { credentials: CredentialProvider; subagents?: workspaceDir: normalizedConfig.workspaceDir ?? process.cwd(), apiHost, isCiDriver: process.env.DSH_GITHUB_CI_DRIVER === '1', - resolveToken: (signal?: AbortSignal) => resolveToken(ctx.credentials, normalizedConfig.tokenSource, normalizedConfig.tokenRef, runGh, signal), + resolveToken: (signal?: AbortSignal) => resolveToken(ctx.credentials, normalizedConfig.tokenSource, normalizedConfig.tokenRef, runGh, signal, liveValue(normalizedConfig.githubToken)), client: (token: string) => new GithubClient(token, clientOptions), graphqlClient: (token: string) => new GithubGraphqlClient(token, clientOptions), resolveRepo: (ownerRepo: string | undefined, signal?: AbortSignal) => resolveRepo(state, ownerRepo, signal), From 529d362c90c3bbe7ac8ee3848b674346c13d651e Mon Sep 17 00:00:00 2001 From: fishdivinity Date: Tue, 27 Oct 2026 15:06:12 +0800 Subject: [PATCH 2/5] fix(client): mount the GitHub card without the credentials remote The browser half required the browser-side credentials remote, which DSH 0.2.1 removed: @deepseek-ai/dsh-credentials exports no ./remote, and nothing else provides that namespace. The client entry therefore stayed pending, which 0.2.x treats as a fatal web boot, and the defensive variant returned before ctx.slots.register, so no card ever appeared in the Plugins panel. The card now reads and writes the form the page supplies, whose shape is { state, mutate } rather than the getSnapshot/subscribe pair the old controller assumed. It registers on plugins.item unconditionally and renders through the shipped SettingsForm and SettingsSecretField, so themes and installed skins restyle it. The page body adds a short guide to the two GitHub token pages. The summary line stays a plain description, because the list render supplies no form to read a state from. dsh.client.inject drops the client packages the card no longer imports. Refs #29 --- lib/client.d.ts | 281 +++++---------------- lib/client.d.ts.map | 2 +- lib/client.js | 365 +++++++++------------------ lib/client.js.map | 2 +- package.json | 2 - src/client.ts | 592 +++++++++++++------------------------------- 6 files changed, 356 insertions(+), 888 deletions(-) diff --git a/lib/client.d.ts b/lib/client.d.ts index e4da811..7440350 100644 --- a/lib/client.d.ts +++ b/lib/client.d.ts @@ -1,93 +1,38 @@ /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card in the Plugins panel's Official group. * - * The card reports and edits the GitHub token. The token literal never rides - * the settings document: it is written through the credentials domain, - * addressed by the reference the plugin's cordis.yml `Config.tokenRef` names - * (default `GITHUB_TOKEN`), which is exactly where the host half resolves it — - * per operation, no restart needed. + * The card reads and writes the plugin's own `Config.githubToken` through the + * configuration form the page hands a `plugins.item` entry (`form.state` and + * `form.mutate`), so the token stays one host-owned field and the host half + * resolves it on every operation. The browser half deliberately depends on no + * credentials remote: DSH 0.2.1 no longer exposes one (`remote.credentials` / + * `remote.credentialsController` are gone), and a missing required client + * service leaves the whole entry pending, which fails the web boot. * - * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * Rendering uses the shipped `SettingsForm` / `SettingsSecretField`, so the + * card inherits the standard settings layout and every theme token a skin + * overrides; the only local CSS is the guidance list below. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. * @module @perrylink/dsh-github/client */ import { type ReactNode } from 'react'; -/** - * The configuration-form contract the card consumes, declared locally: a - * client package must not import a Host package, and the browser half of the - * seam lives in `@deepseek-ai/dsh-client-ui-settings`, which is an optional - * peer. Mirrors that package's `ConfigForm`/`ConfigFormSnapshot` faces — the - * ones the Plugins page hands a `plugins.item` entry as `form`. - */ -/** Client-side sync state of one configuration entry. */ -export interface ConfigFormSnapshot { - /** `loading` until the first accepted section, `ready` while one stands, `unavailable` otherwise. */ - status: 'loading' | 'ready' | 'unavailable'; - /** Last accepted schema-resolved section; undefined before the first acceptance. */ - value: T | undefined; - /** Composition layer the Host resolved the value over, when the owning plugin declared one. */ - base: unknown; - /** Raw user layer as stored, when one exists. */ - user: unknown; - /** Namespace revision fencing the next write; undefined before the first Host view. */ - revision: number | undefined; - /** Whether the Host document accepts writes; memory mode never does. */ - writable: boolean; - /** `host` syncs with the Host document; `memory` keeps a remote browser process-local. */ - mode: 'host' | 'memory'; -} -/** Reactive owner handle over one configuration entry's accepted values. */ -export interface ConfigForm { - /** @returns the current sync snapshot (stable reference until the next change). */ - getSnapshot(): ConfigFormSnapshot; - /** - * Observe snapshot replacements. - * @param listener - invoked after each snapshot change. - * @returns the disposer removing this listener. - */ - subscribe(listener: () => void): () => void; -} -/** - * Minimal writable snapshot store the card's slot hooks consume. Declared and - * implemented locally: its previous home `dsh-client-store` is not on the - * published `0.1.1-rc.2` line, and the card only needs the bare observable - * contract plus whole-value replacement (no drafts, no persistence) — the - * framework synthesizes the selector hook from `getSnapshot`/`subscribe`. - */ -export interface SnapshotStore { - /** @returns the current snapshot reference. */ - getSnapshot(): T; - /** - * Subscribe to snapshot replacements. - * @param listener - invoked after each change. - * @returns the disposer removing this listener. - */ - subscribe(listener: () => void): () => void; - /** - * Replace the state wholesale. - * @param next - next state. - */ - set(next: T): void; +/** Dictionary namespace owned by this plugin. */ +export declare const NS = "dsh-github"; +/** Client services this half requires; both are provided by the web shell. */ +export declare const inject: string[]; +export interface ClientContextLike { + effect(disposer: () => void, label: string): void; + locale: { + bind(namespace: string): (key: keyof GithubCardLocale) => string; + register(namespace: string, dictionaries: Record): void; + }; + slots: { + inject(slot: string, factory: () => unknown): unknown; + register(options: Record, component: unknown): unknown; + }; } -/** - * Create the minimal card store. - * @param init - initial state. - * @returns the store. - */ -export declare function createSnapshotStore(init: T): SnapshotStore; -/** Namespace of the GitHub capability. Spelled here rather than imported: a client package must not depend on a Host package. */ -export declare const GITHUB_NS = "dsh-github"; -/** Credential reference the provider resolves when the configuration names none. */ -export declare const DEFAULT_TOKEN_REF = "GITHUB_TOKEN"; /** Locale copy the card renders. */ export interface GithubCardLocale { githubTitle: string; @@ -96,177 +41,67 @@ export interface GithubCardLocale { tokenHint: string; tokenSet: string; tokenUnset: string; - unsaved: string; + unavailable: string; readOnly: string; save: string; saving: string; - discard: string; saveFailed: string; + guideIntro: string; + guideClassic: string; + guideFineGrained: string; + guideStorage: string; } /** English copy. */ export declare const en: GithubCardLocale; /** Simplified Chinese copy. */ export declare const zh: GithubCardLocale; -/** The card's full state, as projected into its snapshot store. */ -export interface GithubCardState { +/** Sync state of one configuration entry, as the Plugins page projects it. */ +export interface ConfigFormSnapshot { + /** `loading` until the first accepted section, `ready` while one stands, `unavailable` otherwise. */ + status: 'loading' | 'ready' | 'unavailable'; + /** Last accepted schema-resolved section; undefined before the first acceptance. */ + value: T | undefined; + /** Namespace revision fencing the next write; undefined before the first Host view. */ + revision: number | undefined; /** Whether the Host configuration document accepts writes. */ writable: boolean; - /** Whether the referenced credential is configured. */ - configured: boolean; - /** Whether the credentials domain accepts writes. */ - credentialWritable: boolean; - /** Whether a save is crossing the wire. */ - saving: boolean; - /** Whether the last save did not land as staged. */ - failed: boolean; - /** The credential reference the card addresses. */ - ref: string; } -/** Source and writability facts for one credential reference (never the value). */ -interface CredentialView { - /** Whether resolving the reference would currently return a value. */ - configured: boolean; - /** Source layer currently supplying the value; absent while unconfigured. */ - source?: string; - /** Whether the active provider can write this reference. */ - writable: boolean; +/** One ordered mutation the configuration form applies to its namespace. */ +export interface ConfigFormOp { + op: 'set' | 'unset'; + path: string[]; + value?: unknown; } /** - * The credentials-domain wire face the card uses: the host `credentials` Remote - * namespace (`remote.credentials`). The token literal crosses the wire on - * `set` only — no read path returns it. + * The configuration-form face the Plugins page hands a `plugins.item` entry. + * Mirrors the page's own `ConfigPageForm`: a snapshot plus the write action. */ -export interface CredentialsApi { - /** - * Ask the credentials domain about references; one view per requested name, - * keyed by that name. - */ - describe(refs: string[]): Promise<{ - readonly ok: true; - readonly value: Record; - } | { - readonly ok: false; - readonly error: { - readonly code: string; - readonly message: string; - }; - }>; - /** - * Store one non-empty value under a reference. - */ - set(ref: string, value: string): Promise; +export interface ConfigPageForm { + state: ConfigFormSnapshot; + mutate(ops: ConfigFormOp[], revision?: number): Promise; } -/** The configuration the card reads its credential reference from (the plugin's own `Config` subset). */ -interface GithubCardConfig { - tokenRef?: string; -} -/** - * Bridges the page-supplied configuration form and the credentials domain onto - * the card. The token is the one control that does not live in the - * configuration: its literal never rides a response, so the card learns only - * whether one is configured and writes it through the credentials domain, - * addressed by the reference `Config.tokenRef` names. - */ -export declare class GithubCardController { - private readonly form; - private readonly api; - private readonly store; - private saving; - private failed; - private credential; - /** - * @param form - the configuration form the Plugins page hands this entry, or - * `undefined` when the page supplied none (the card then reads the default - * reference and offers the credential control alone). - * @param api - the credentials Remote namespace. - */ - constructor(form: ConfigForm | undefined, api: CredentialsApi); - /** Whether the Host configuration document accepts writes. */ - writable(): boolean; - /** The configuration form this controller reads (identity-compared by the caller). */ - formOf(): ConfigForm | undefined; - /** Project the card's full state for its snapshot store. */ - projection(): GithubCardState; - /** The credential reference the configuration names, or the provider default. */ - refOf(): string; - /** - * Ask the credentials domain about the reference the section names. A - * response is published only while it still answers for the reference in - * force, so two reads settling out of order cannot clobber each other. - */ - readCredential(): Promise; - /** - * Re-read after the Host reports a change to the reference this card - * watches — a token can be written from elsewhere, and the section does not - * change when it is. - * @param ref - the reference the Host reports as changed. - */ - refreshCredential(ref: string): void; - /** - * Write the staged token, then re-read whether the Host now holds one. A - * blank value writes nothing, which keeps the stored key. - * @param value - the staged credential literal. - * @returns whether the Host reports a configured credential afterwards. - */ - save(value: string): Promise; - /** Build the face the card's slot registration injects. */ - inject(): { - hooks: { - githubCard: SnapshotStore; - }; - submit: (value: string) => Promise; - }; - private publish; +/** The plugin configuration subset this card reads and writes. */ +export interface GithubCardConfig { + githubToken?: string; } /** Props the slot system injects into the card component. */ export interface GithubCardProps { t: (key: keyof GithubCardLocale) => string; - useGithubCard: (selector: (snapshot: GithubCardState) => GithubCardState) => GithubCardState; - submit: (value: string) => Promise; /** The view the Plugins page asks for: the one-liner under the title, or the page body. */ view: 'summary' | 'page'; + /** The form for this entry; absent when the page has no editable configuration for it. */ + form?: ConfigPageForm | undefined; } /** - * Render the GitHub card. `summary` renders the one-liner the Plugins page - * places under the card's title (the description plus the token state badge); - * `page` renders the token control and the save/discard row on the plugin's - * own page. The page supplies the configuration form, so the card never - * depends on a served namespace to render. + * Render the GitHub card: the one-liner the page shows under the card's title, + * or the token control on the plugin's own page. + * @param props - locale, view, and the page-supplied configuration form. + * @returns the card's React node. */ export declare function GithubCard(props: GithubCardProps): ReactNode; -/** Dictionary namespace owned by this plugin. */ -export declare const NS = "dsh-github"; -/** - * Required services (cordis fiber inject). `settingsScope` is gone: host - * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. - */ -export declare const inject: string[]; -export interface ClientContextLike { - get(service: string): unknown; - effect(disposer: () => void, label: string): void; - locale: { - bind(namespace: string): (key: keyof GithubCardLocale) => string; - register(namespace: string, dictionaries: Record): void; - }; - remote: { - $on(event: string, listener: (ref: string) => void): unknown; - credentials: CredentialsApi; - }; - slots: { - inject(slot: string, factory: () => unknown): unknown; - register(options: Record, component: unknown): unknown; - }; -} /** - * Mount the GitHub configuration card into the Plugins page's Official group. - * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * Mount the GitHub configuration card into the Plugins panel's Official group. * @param ctx - the browser plugin context. */ export declare function apply(ctx: ClientContextLike): void; -export {}; //# sourceMappingURL=client.d.ts.map \ No newline at end of file diff --git a/lib/client.d.ts.map b/lib/client.d.ts.map index 45fa86c..ab5d32a 100644 --- a/lib/client.d.ts.map +++ b/lib/client.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/client.js b/lib/client.js index 0d022a1..6ac33ff 100755 --- a/lib/client.js +++ b/lib/client.js @@ -5,24 +5,21 @@ window.__ModuleLoader__.load({ var exports = module.exports; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const { createElement, useState } = require("react"); - const { Button, IconLoadingOutlineRegular, } = require("@deepseek-ai/dsh-client-ui-primitives"); + const { SettingsForm, SettingsSecretField } = require("@deepseek-ai/dsh-client-ui-primitives"); /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card in the Plugins panel's Official group. * - * The card reports and edits the GitHub token. The token literal never rides - * the settings document: it is written through the credentials domain, - * addressed by the reference the plugin's cordis.yml `Config.tokenRef` names - * (default `GITHUB_TOKEN`), which is exactly where the host half resolves it — - * per operation, no restart needed. + * The card reads and writes the plugin's own `Config.githubToken` through the + * configuration form the page hands a `plugins.item` entry (`form.state` and + * `form.mutate`), so the token stays one host-owned field and the host half + * resolves it on every operation. The browser half deliberately depends on no + * credentials remote: DSH 0.2.1 no longer exposes one (`remote.credentials` / + * `remote.credentialsController` are gone), and a missing required client + * service leaves the whole entry pending, which fails the web boot. * - * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * Rendering uses the shipped `SettingsForm` / `SettingsSecretField`, so the + * card inherits the standard settings layout and every theme token a skin + * overrides; the only local CSS is the guidance list below. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. @@ -30,282 +27,162 @@ window.__ModuleLoader__.load({ */ - /** - * Create the minimal card store. - * @param init - initial state. - * @returns the store. - */ - function createSnapshotStore(init) { - let state = init; - const listeners = new Set(); - return { - getSnapshot: () => state, - subscribe: (listener) => { - listeners.add(listener); - return () => { listeners.delete(listener); }; - }, - set: (next) => { - state = next; - for (const listener of [...listeners]) - listener(); - }, - }; - } - /** Namespace of the GitHub capability. Spelled here rather than imported: a client package must not depend on a Host package. */ - const GITHUB_NS = 'dsh-github'; - /** Credential reference the provider resolves when the configuration names none. */ - const DEFAULT_TOKEN_REF = 'GITHUB_TOKEN'; + /** Dictionary namespace owned by this plugin. */ + const NS = 'dsh-github'; + /** Client services this half requires; both are provided by the web shell. */ + const inject = ['slots', 'locale']; /** English copy. */ const en = { githubTitle: 'GitHub', githubDescription: 'GitHub pull requests, issues, and CI through the agent.', tokenLabel: 'GitHub token', - tokenHint: 'Stored in the credentials file, not here. Applied immediately; leave blank to keep the current token.', - tokenSet: 'A token is configured.', - tokenUnset: 'No token is configured; GitHub tools are unavailable until one is.', - unsaved: 'Unsaved', + tokenHint: 'Save writes this plugin\'s configuration in plain text and applies on the next GitHub operation; leave it blank to keep the current token.', + tokenSet: 'Token configured', + tokenUnset: 'No token', + unavailable: 'This page has no editable configuration form; set `githubToken` in the profile configuration instead.', readOnly: 'This deployment stores settings read-only.', save: 'Save', saving: 'Saving…', - discard: 'Discard', saveFailed: 'The deployment did not accept this value; it was left for you to correct.', + guideIntro: 'No token yet? Create a personal access token on GitHub:', + guideClassic: 'Classic token — Settings → Developer settings → Personal access tokens (classic), scope `repo`:', + guideFineGrained: 'Fine-grained token — pick the repositories and grant Contents, Issues, and Pull requests read/write:', + guideStorage: 'Paste the whole string (ghp_… or github_pat_…). A token is a password: never commit it or share it.', }; /** Simplified Chinese copy. */ const zh = { githubTitle: 'GitHub', githubDescription: '通过 agent 操作 GitHub 的 PR、issue 与 CI。', tokenLabel: 'GitHub Token', - tokenHint: '写入凭证文件而非设置文件;保存后立即生效。留空表示保持现有令牌。', - tokenSet: '已配置令牌。', - tokenUnset: '未配置令牌;配置之前 GitHub 工具不可用。', - unsaved: '未保存', + tokenHint: '保存后以明文写入本插件配置,下一次 GitHub 操作即生效;留空表示保持现有令牌。', + tokenSet: '已配置', + tokenUnset: '未配置', + unavailable: '本页没有可编辑的配置表单;请在 profile 配置里填写 `githubToken`。', readOnly: '本部署的设置为只读。', save: '保存', saving: '保存中…', - discard: '放弃修改', saveFailed: '本部署没有接受该值,已保留供你修改。', + guideIntro: '还没有令牌?先在 GitHub 生成一个个人访问令牌(PAT):', + guideClassic: '经典令牌:Settings → Developer settings → Personal access tokens (classic),勾选 `repo`:', + guideFineGrained: '细粒度令牌:Personal access tokens (fine-grained),选好仓库并给 Contents、Issues、Pull requests 读写:', + guideStorage: '把整串(ghp_… 或 github_pat_…)粘到上面的输入框。令牌等同于密码,不要提交进仓库或贴到公开的地方。', }; + /** Guidance list styling; everything else comes from the shipped settings primitives. */ + const CARD_CSS = [ + '.ghc-guide{margin-top:12px;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary);}', + '.ghc-guide p{margin:0 0 4px;}', + '.ghc-guide ul{margin:0 0 4px;padding-left:18px;}', + '.ghc-guide li{margin:0 0 2px;}', + '.ghc-guide a{color:var(--dsw-alias-brand-primary);text-decoration:none;}', + '.ghc-guide a:hover{text-decoration:underline;}', + ].join(''); /** - * Bridges the page-supplied configuration form and the credentials domain onto - * the card. The token is the one control that does not live in the - * configuration: its literal never rides a response, so the card learns only - * whether one is configured and writes it through the credentials domain, - * addressed by the reference `Config.tokenRef` names. + * Render the GitHub card: the one-liner the page shows under the card's title, + * or the token control on the plugin's own page. + * @param props - locale, view, and the page-supplied configuration form. + * @returns the card's React node. */ - class GithubCardController { - form; - api; - store; - saving = false; - failed = false; - credential = { ref: '', configured: false, writable: true }; - /** - * @param form - the configuration form the Plugins page hands this entry, or - * `undefined` when the page supplied none (the card then reads the default - * reference and offers the credential control alone). - * @param api - the credentials Remote namespace. - */ - constructor(form, api) { - this.form = form; - this.api = api; - this.store = createSnapshotStore(this.projection()); - form?.subscribe(() => { - void this.readCredential(); - this.publish(); - }); - void this.readCredential(); - } - /** Whether the Host configuration document accepts writes. */ - writable() { - return this.form?.getSnapshot().writable ?? true; - } - /** The configuration form this controller reads (identity-compared by the caller). */ - formOf() { - return this.form; - } - /** Project the card's full state for its snapshot store. */ - projection() { - return { - writable: this.writable(), - configured: this.credential.configured, - credentialWritable: this.credential.writable, - saving: this.saving, - failed: this.failed, - ref: this.credential.ref, - }; - } - /** The credential reference the configuration names, or the provider default. */ - refOf() { - const declared = this.form?.getSnapshot().value?.tokenRef; - return declared !== undefined && declared.length > 0 ? declared : DEFAULT_TOKEN_REF; - } - /** - * Ask the credentials domain about the reference the section names. A - * response is published only while it still answers for the reference in - * force, so two reads settling out of order cannot clobber each other. - */ - async readCredential() { - const ref = this.refOf(); - if (ref !== this.credential.ref) { - this.credential = { ref, configured: false, writable: true }; - this.publish(); - } - let response; - try { - response = await this.api.describe([ref]); - } - catch { - return; - } - if (!response.ok || ref !== this.refOf()) - return; - const view = response.value[ref]; - const next = { ref, configured: view?.configured ?? false, writable: view?.writable ?? true }; - if (next.configured === this.credential.configured && next.writable === this.credential.writable) - return; - this.credential = next; - this.publish(); - } - /** - * Re-read after the Host reports a change to the reference this card - * watches — a token can be written from elsewhere, and the section does not - * change when it is. - * @param ref - the reference the Host reports as changed. - */ - refreshCredential(ref) { - if (ref !== this.credential.ref) + function GithubCard(props) { + const { t, form } = props; + const [draft, setDraft] = useState(''); + const [saving, setSaving] = useState(false); + const [failed, setFailed] = useState(false); + const stored = (form?.state.value?.githubToken ?? '').trim(); + const configured = stored.length > 0; + // A summary render receives no `form` (the page hands it only to the detail + // view), so it must not claim a token state it cannot read; the badge on the + // page view is the single source of that answer. + if (props.view === 'summary') + return t('githubDescription'); + const writable = form?.state.writable ?? false; + const staged = draft.trim(); + const save = async () => { + if (form === undefined || staged === '' || saving) return; - void this.readCredential(); - } - /** - * Write the staged token, then re-read whether the Host now holds one. A - * blank value writes nothing, which keeps the stored key. - * @param value - the staged credential literal. - * @returns whether the Host reports a configured credential afterwards. - */ - async save(value) { - const text = (value ?? '').trim(); - if (text === '' || this.saving) - return false; - this.saving = true; - this.failed = false; - this.publish(); + setSaving(true); + setFailed(false); + let landed = false; try { - await this.api.set(this.refOf(), text); + // No explicit revision: the form fences the write with the latest one it + // knows, so a save queued behind another write cannot be rejected as stale. + landed = await form.mutate([{ op: 'set', path: ['githubToken'], value: staged }]); } catch { - // handled below by re-reading the configured state + landed = false; } - await this.readCredential(); - const landed = this.credential.configured; - this.saving = false; - this.failed = !landed; - this.publish(); - return landed; - } - /** Build the face the card's slot registration injects. */ - inject() { - return { - hooks: { githubCard: this.store }, - submit: (value) => this.save(value), - }; - } - publish() { - this.store.set(this.projection()); - } - } - /** - * Render the GitHub card. `summary` renders the one-liner the Plugins page - * places under the card's title (the description plus the token state badge); - * `page` renders the token control and the save/discard row on the plugin's - * own page. The page supplies the configuration form, so the card never - * depends on a served namespace to render. - */ - function GithubCard(props) { - const { t } = props; - const state = props.useGithubCard((snapshot) => snapshot); - const [draft, setDraft] = useState(''); - if (props.view === 'summary') { - return createElement('span', { className: 'ghc-summary' }, createElement('span', null, t('githubDescription')), createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset'))); - } - const dirty = draft.trim() !== ''; - const saveLabel = state.saving ? t('saving') : t('save'); - return createElement('div', { className: 'ghc-card ghc-cardPage' }, !state.writable - ? createElement('p', { className: 'ghc-readOnly', role: 'status' }, t('readOnly')) - : null, createElement('div', { className: 'ghc-field' }, createElement('div', { className: 'ghc-head' }, createElement('label', { className: 'ghc-label', htmlFor: 'plugin-config-github-token' }, t('tokenLabel')), createElement('span', { className: 'ghc-badges' }, createElement('span', { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, state.configured ? t('tokenSet') : t('tokenUnset')))), createElement('input', { - id: 'plugin-config-github-token', - className: 'ghc-input', - type: 'password', - autoComplete: 'off', - value: draft, - disabled: !state.credentialWritable, - onChange: (event) => setDraft(event.target.value), - }), createElement('p', { className: 'ghc-hint' }, t('tokenHint'))), createElement('div', { className: 'ghc-actions' }, state.failed ? createElement('p', { className: 'ghc-failed', role: 'status' }, t('saveFailed')) : null, createElement(Button, { - variant: 'ghost', - size: 'sm', - disabled: !dirty || state.saving, - onClick: () => setDraft(''), - }, t('discard')), createElement(Button, { - variant: 'primary', - size: 'sm', - disabled: !state.writable || !dirty || state.saving, - icon: state.saving - ? createElement('span', { className: 'ghc-spin' }, createElement(IconLoadingOutlineRegular, { size: 16 })) - : undefined, - onClick: async () => { - const landed = await props.submit(draft); - if (landed) - setDraft(''); + setSaving(false); + if (landed) + setDraft(''); + else + setFailed(true); + }; + return createElement(SettingsForm, { + labels: { + unavailable: t('unavailable'), + readOnly: t('readOnly'), + saveFailed: t('saveFailed'), + save: t('save'), + saving: t('saving'), + }, + state: { + available: form !== undefined, + writable, + dirty: staged !== '', + invalid: false, + saving, + failed, }, - }, saveLabel))); + onSave: () => { void save(); }, + // SettingsForm calls this only on unmount; the draft belongs to the + // component instance, so a fresh mount starts clean either way. + onDiscard: () => { }, + children: [ + createElement(SettingsSecretField, { + id: 'plugin-config-github-token', + label: t('tokenLabel'), + configured, + stateLabel: configured ? t('tokenSet') : t('tokenUnset'), + text: draft, + hint: t('tokenHint'), + disabled: !writable || saving, + onEdit: (text) => setDraft(text), + }), + createElement('div', { className: 'ghc-guide' }, createElement('p', null, t('guideIntro')), createElement('ul', null, createElement('li', null, t('guideClassic'), ' ', createElement('a', { href: 'https://github.com/settings/tokens', target: '_blank', rel: 'noreferrer noopener' }, 'github.com/settings/tokens')), createElement('li', null, t('guideFineGrained'), ' ', createElement('a', { href: 'https://github.com/settings/personal-access-tokens/new', target: '_blank', rel: 'noreferrer noopener' }, 'github.com/settings/personal-access-tokens/new'))), createElement('p', null, t('guideStorage'))), + ], + }); } - /** Dictionary namespace owned by this plugin. */ - const NS = 'dsh-github'; /** - * Required services (cordis fiber inject). `settingsScope` is gone: host - * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. - */ - const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials']; - /** - * Mount the GitHub configuration card into the Plugins page's Official group. - * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * Mount the GitHub configuration card into the Plugins panel's Official group. * @param ctx - the browser plugin context. */ function apply(ctx) { const t = ctx.locale.bind(NS); ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-github: card dictionaries'); - let github; - const controllerFor = (form) => { - if (github === undefined || github.formOf() !== form) { - github = new GithubCardController(form, ctx.remote.credentials); - } - return github; - }; - ctx.effect(() => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), 'dsh-github: credential invalidations'); + ctx.effect(() => { + const tagId = `${NS}/card.css`; + if (document.querySelector(`style[data-plugin-css="${tagId}"]`) !== null) + return () => { }; + const tag = document.createElement('style'); + tag.dataset.plugin = NS; + tag.dataset.pluginCss = tagId; + tag.textContent = CARD_CSS; + document.head.appendChild(tag); + return () => { tag.remove(); }; + }, 'dsh-github: card styles'); ctx.slots.inject('plugins.item', () => ctx.slots.register({ name: 'plugins.item', id: NS, order: 100, label: () => t('githubTitle'), locale: NS, - inject: () => controllerFor(github?.formOf()).inject(), }, GithubCard)); } - exports.createSnapshotStore = createSnapshotStore; - exports.GithubCardController = GithubCardController; exports.GithubCard = GithubCard; exports.apply = apply; - exports.GITHUB_NS = GITHUB_NS; - exports.DEFAULT_TOKEN_REF = DEFAULT_TOKEN_REF; - exports.en = en; - exports.zh = zh; exports.NS = NS; exports.inject = inject; + exports.en = en; + exports.zh = zh; return module.exports; } }); diff --git a/lib/client.js.map b/lib/client.js.map index e8bb1fc..ea11cf4 100644 --- a/lib/client.js.map +++ b/lib/client.js.map @@ -1 +1 @@ -{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package.json b/package.json index d22177f..786a2d8 100644 --- a/package.json +++ b/package.json @@ -72,10 +72,8 @@ }, "client": { "inject": [ - "@deepseek-ai/dsh-client-connection", "@deepseek-ai/dsh-client-locale", "@deepseek-ai/dsh-client-ui-plugin-manager", - "@deepseek-ai/dsh-client-ui-settings", "@deepseek-ai/dsh-client-ui-slots" ], "platform": "web" diff --git a/src/client.ts b/src/client.ts index 32ae7b3..1eb0289 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,117 +1,43 @@ /** - * dsh-github browser half — one card in the Plugins page's Official group. + * dsh-github browser half — one card in the Plugins panel's Official group. * - * The card reports and edits the GitHub token. The token literal never rides - * the settings document: it is written through the credentials domain, - * addressed by the reference the plugin's cordis.yml `Config.tokenRef` names - * (default `GITHUB_TOKEN`), which is exactly where the host half resolves it — - * per operation, no restart needed. + * The card reads and writes the plugin's own `Config.githubToken` through the + * configuration form the page hands a `plugins.item` entry (`form.state` and + * `form.mutate`), so the token stays one host-owned field and the host half + * resolves it on every operation. The browser half deliberately depends on no + * credentials remote: DSH 0.2.1 no longer exposes one (`remote.credentials` / + * `remote.credentialsController` are gone), and a missing required client + * service leaves the whole entry pending, which fails the web boot. * - * Since host 0.1.7-alpha.1 the page owns configuration: the card renders the - * `summary` one-liner and the `page` body from the `plugins.item` owner props - * (`view`, and the `form` the Plugins page supplies), instead of binding a - * `settingsScope` itself — that service, `settings.plugin.item`'s old shape, - * and the `dsh-settings-file` package behind them were all removed. The card - * therefore reads `tokenRef` from `form.state.value` and never writes the - * settings document; the credential is written through the credentials - * domain, which is a different seam and stayed. + * Rendering uses the shipped `SettingsForm` / `SettingsSecretField`, so the + * card inherits the standard settings layout and every theme token a skin + * overrides; the only local CSS is the guidance list below. * * The shipped `lib/client.js` is the built bundle of this module. The browser * module loader executes that bundle, not this file. * @module @perrylink/dsh-github/client */ -import { createElement, useState, type ChangeEvent, type ReactNode } from 'react' -import { - Button, IconLoadingOutlineRegular, -} from '@deepseek-ai/dsh-client-ui-primitives' +import { createElement, useState, type ReactNode } from 'react' +import { SettingsForm, SettingsSecretField } from '@deepseek-ai/dsh-client-ui-primitives' -/** - * The configuration-form contract the card consumes, declared locally: a - * client package must not import a Host package, and the browser half of the - * seam lives in `@deepseek-ai/dsh-client-ui-settings`, which is an optional - * peer. Mirrors that package's `ConfigForm`/`ConfigFormSnapshot` faces — the - * ones the Plugins page hands a `plugins.item` entry as `form`. - */ - -/** Client-side sync state of one configuration entry. */ -export interface ConfigFormSnapshot { - /** `loading` until the first accepted section, `ready` while one stands, `unavailable` otherwise. */ - status: 'loading' | 'ready' | 'unavailable' - /** Last accepted schema-resolved section; undefined before the first acceptance. */ - value: T | undefined - /** Composition layer the Host resolved the value over, when the owning plugin declared one. */ - base: unknown - /** Raw user layer as stored, when one exists. */ - user: unknown - /** Namespace revision fencing the next write; undefined before the first Host view. */ - revision: number | undefined - /** Whether the Host document accepts writes; memory mode never does. */ - writable: boolean - /** `host` syncs with the Host document; `memory` keeps a remote browser process-local. */ - mode: 'host' | 'memory' -} - -/** Reactive owner handle over one configuration entry's accepted values. */ -export interface ConfigForm { - /** @returns the current sync snapshot (stable reference until the next change). */ - getSnapshot(): ConfigFormSnapshot - /** - * Observe snapshot replacements. - * @param listener - invoked after each snapshot change. - * @returns the disposer removing this listener. - */ - subscribe(listener: () => void): () => void -} +/** Dictionary namespace owned by this plugin. */ +export const NS = 'dsh-github' -/** - * Minimal writable snapshot store the card's slot hooks consume. Declared and - * implemented locally: its previous home `dsh-client-store` is not on the - * published `0.1.1-rc.2` line, and the card only needs the bare observable - * contract plus whole-value replacement (no drafts, no persistence) — the - * framework synthesizes the selector hook from `getSnapshot`/`subscribe`. - */ -export interface SnapshotStore { - /** @returns the current snapshot reference. */ - getSnapshot(): T - /** - * Subscribe to snapshot replacements. - * @param listener - invoked after each change. - * @returns the disposer removing this listener. - */ - subscribe(listener: () => void): () => void - /** - * Replace the state wholesale. - * @param next - next state. - */ - set(next: T): void -} +/** Client services this half requires; both are provided by the web shell. */ +export const inject = ['slots', 'locale'] -/** - * Create the minimal card store. - * @param init - initial state. - * @returns the store. - */ -export function createSnapshotStore(init: T): SnapshotStore { - let state = init - const listeners = new Set<() => void>() - return { - getSnapshot: () => state, - subscribe: (listener) => { - listeners.add(listener) - return () => { listeners.delete(listener) } - }, - set: (next) => { - state = next - for (const listener of [...listeners]) listener() - }, +export interface ClientContextLike { + effect(disposer: () => void, label: string): void + locale: { + bind(namespace: string): (key: keyof GithubCardLocale) => string + register(namespace: string, dictionaries: Record): void + } + slots: { + inject(slot: string, factory: () => unknown): unknown + register(options: Record, component: unknown): unknown } } -/** Namespace of the GitHub capability. Spelled here rather than imported: a client package must not depend on a Host package. */ -export const GITHUB_NS = 'dsh-github' -/** Credential reference the provider resolves when the configuration names none. */ -export const DEFAULT_TOKEN_REF = 'GITHUB_TOKEN' - /** Locale copy the card renders. */ export interface GithubCardLocale { githubTitle: string @@ -120,12 +46,15 @@ export interface GithubCardLocale { tokenHint: string tokenSet: string tokenUnset: string - unsaved: string + unavailable: string readOnly: string save: string saving: string - discard: string saveFailed: string + guideIntro: string + guideClassic: string + guideFineGrained: string + guideStorage: string } /** English copy. */ @@ -133,15 +62,18 @@ export const en: GithubCardLocale = { githubTitle: 'GitHub', githubDescription: 'GitHub pull requests, issues, and CI through the agent.', tokenLabel: 'GitHub token', - tokenHint: 'Stored in the credentials file, not here. Applied immediately; leave blank to keep the current token.', - tokenSet: 'A token is configured.', - tokenUnset: 'No token is configured; GitHub tools are unavailable until one is.', - unsaved: 'Unsaved', + tokenHint: 'Save writes this plugin\'s configuration in plain text and applies on the next GitHub operation; leave it blank to keep the current token.', + tokenSet: 'Token configured', + tokenUnset: 'No token', + unavailable: 'This page has no editable configuration form; set `githubToken` in the profile configuration instead.', readOnly: 'This deployment stores settings read-only.', save: 'Save', saving: 'Saving…', - discard: 'Discard', saveFailed: 'The deployment did not accept this value; it was left for you to correct.', + guideIntro: 'No token yet? Create a personal access token on GitHub:', + guideClassic: 'Classic token — Settings → Developer settings → Personal access tokens (classic), scope `repo`:', + guideFineGrained: 'Fine-grained token — pick the repositories and grant Contents, Issues, and Pull requests read/write:', + guideStorage: 'Paste the whole string (ghp_… or github_pat_…). A token is a password: never commit it or share it.', } /** Simplified Chinese copy. */ @@ -149,359 +81,186 @@ export const zh: GithubCardLocale = { githubTitle: 'GitHub', githubDescription: '通过 agent 操作 GitHub 的 PR、issue 与 CI。', tokenLabel: 'GitHub Token', - tokenHint: '写入凭证文件而非设置文件;保存后立即生效。留空表示保持现有令牌。', - tokenSet: '已配置令牌。', - tokenUnset: '未配置令牌;配置之前 GitHub 工具不可用。', - unsaved: '未保存', + tokenHint: '保存后以明文写入本插件配置,下一次 GitHub 操作即生效;留空表示保持现有令牌。', + tokenSet: '已配置', + tokenUnset: '未配置', + unavailable: '本页没有可编辑的配置表单;请在 profile 配置里填写 `githubToken`。', readOnly: '本部署的设置为只读。', save: '保存', saving: '保存中…', - discard: '放弃修改', saveFailed: '本部署没有接受该值,已保留供你修改。', + guideIntro: '还没有令牌?先在 GitHub 生成一个个人访问令牌(PAT):', + guideClassic: '经典令牌:Settings → Developer settings → Personal access tokens (classic),勾选 `repo`:', + guideFineGrained: '细粒度令牌:Personal access tokens (fine-grained),选好仓库并给 Contents、Issues、Pull requests 读写:', + guideStorage: '把整串(ghp_… 或 github_pat_…)粘到上面的输入框。令牌等同于密码,不要提交进仓库或贴到公开的地方。', } -/** The card's full state, as projected into its snapshot store. */ -export interface GithubCardState { +/** Sync state of one configuration entry, as the Plugins page projects it. */ +export interface ConfigFormSnapshot { + /** `loading` until the first accepted section, `ready` while one stands, `unavailable` otherwise. */ + status: 'loading' | 'ready' | 'unavailable' + /** Last accepted schema-resolved section; undefined before the first acceptance. */ + value: T | undefined + /** Namespace revision fencing the next write; undefined before the first Host view. */ + revision: number | undefined /** Whether the Host configuration document accepts writes. */ writable: boolean - /** Whether the referenced credential is configured. */ - configured: boolean - /** Whether the credentials domain accepts writes. */ - credentialWritable: boolean - /** Whether a save is crossing the wire. */ - saving: boolean - /** Whether the last save did not land as staged. */ - failed: boolean - /** The credential reference the card addresses. */ - ref: string } -/** Source and writability facts for one credential reference (never the value). */ -interface CredentialView { - /** Whether resolving the reference would currently return a value. */ - configured: boolean - /** Source layer currently supplying the value; absent while unconfigured. */ - source?: string - /** Whether the active provider can write this reference. */ - writable: boolean +/** One ordered mutation the configuration form applies to its namespace. */ +export interface ConfigFormOp { + op: 'set' | 'unset' + path: string[] + value?: unknown } /** - * The credentials-domain wire face the card uses: the host `credentials` Remote - * namespace (`remote.credentials`). The token literal crosses the wire on - * `set` only — no read path returns it. + * The configuration-form face the Plugins page hands a `plugins.item` entry. + * Mirrors the page's own `ConfigPageForm`: a snapshot plus the write action. */ -export interface CredentialsApi { - /** - * Ask the credentials domain about references; one view per requested name, - * keyed by that name. - */ - describe(refs: string[]): Promise< - | { readonly ok: true; readonly value: Record } - | { readonly ok: false; readonly error: { readonly code: string; readonly message: string } } - > - /** - * Store one non-empty value under a reference. - */ - set(ref: string, value: string): Promise +export interface ConfigPageForm { + state: ConfigFormSnapshot + mutate(ops: ConfigFormOp[], revision?: number): Promise } -/** The configuration the card reads its credential reference from (the plugin's own `Config` subset). */ -interface GithubCardConfig { - tokenRef?: string -} - -/** - * Bridges the page-supplied configuration form and the credentials domain onto - * the card. The token is the one control that does not live in the - * configuration: its literal never rides a response, so the card learns only - * whether one is configured and writes it through the credentials domain, - * addressed by the reference `Config.tokenRef` names. - */ -export class GithubCardController { - private readonly form: ConfigForm | undefined - private readonly api: CredentialsApi - private readonly store: SnapshotStore - private saving = false - private failed = false - private credential: { ref: string; configured: boolean; writable: boolean } = { ref: '', configured: false, writable: true } - - /** - * @param form - the configuration form the Plugins page hands this entry, or - * `undefined` when the page supplied none (the card then reads the default - * reference and offers the credential control alone). - * @param api - the credentials Remote namespace. - */ - constructor(form: ConfigForm | undefined, api: CredentialsApi) { - this.form = form - this.api = api - this.store = createSnapshotStore(this.projection()) - form?.subscribe(() => { - void this.readCredential() - this.publish() - }) - void this.readCredential() - } - - /** Whether the Host configuration document accepts writes. */ - writable(): boolean { - return this.form?.getSnapshot().writable ?? true - } - - /** The configuration form this controller reads (identity-compared by the caller). */ - formOf(): ConfigForm | undefined { - return this.form - } - - /** Project the card's full state for its snapshot store. */ - projection(): GithubCardState { - return { - writable: this.writable(), - configured: this.credential.configured, - credentialWritable: this.credential.writable, - saving: this.saving, - failed: this.failed, - ref: this.credential.ref, - } - } - - /** The credential reference the configuration names, or the provider default. */ - refOf(): string { - const declared = this.form?.getSnapshot().value?.tokenRef - return declared !== undefined && declared.length > 0 ? declared : DEFAULT_TOKEN_REF - } - - /** - * Ask the credentials domain about the reference the section names. A - * response is published only while it still answers for the reference in - * force, so two reads settling out of order cannot clobber each other. - */ - async readCredential(): Promise { - const ref = this.refOf() - if (ref !== this.credential.ref) { - this.credential = { ref, configured: false, writable: true } - this.publish() - } - let response - try { - response = await this.api.describe([ref]) - } catch { - return - } - if (!response.ok || ref !== this.refOf()) return - const view = response.value[ref] - const next = { ref, configured: view?.configured ?? false, writable: view?.writable ?? true } - if (next.configured === this.credential.configured && next.writable === this.credential.writable) return - this.credential = next - this.publish() - } - - /** - * Re-read after the Host reports a change to the reference this card - * watches — a token can be written from elsewhere, and the section does not - * change when it is. - * @param ref - the reference the Host reports as changed. - */ - refreshCredential(ref: string): void { - if (ref !== this.credential.ref) return - void this.readCredential() - } - - /** - * Write the staged token, then re-read whether the Host now holds one. A - * blank value writes nothing, which keeps the stored key. - * @param value - the staged credential literal. - * @returns whether the Host reports a configured credential afterwards. - */ - async save(value: string): Promise { - const text = (value ?? '').trim() - if (text === '' || this.saving) return false - this.saving = true - this.failed = false - this.publish() - try { - await this.api.set(this.refOf(), text) - } catch { - // handled below by re-reading the configured state - } - await this.readCredential() - const landed = this.credential.configured - this.saving = false - this.failed = !landed - this.publish() - return landed - } - - /** Build the face the card's slot registration injects. */ - inject(): { hooks: { githubCard: SnapshotStore }; submit: (value: string) => Promise } { - return { - hooks: { githubCard: this.store }, - submit: (value) => this.save(value), - } - } - - private publish(): void { - this.store.set(this.projection()) - } +/** The plugin configuration subset this card reads and writes. */ +export interface GithubCardConfig { + githubToken?: string } /** Props the slot system injects into the card component. */ export interface GithubCardProps { t: (key: keyof GithubCardLocale) => string - useGithubCard: (selector: (snapshot: GithubCardState) => GithubCardState) => GithubCardState - submit: (value: string) => Promise /** The view the Plugins page asks for: the one-liner under the title, or the page body. */ view: 'summary' | 'page' + /** The form for this entry; absent when the page has no editable configuration for it. */ + form?: ConfigPageForm | undefined } +/** Guidance list styling; everything else comes from the shipped settings primitives. */ +const CARD_CSS = [ + '.ghc-guide{margin-top:12px;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary);}', + '.ghc-guide p{margin:0 0 4px;}', + '.ghc-guide ul{margin:0 0 4px;padding-left:18px;}', + '.ghc-guide li{margin:0 0 2px;}', + '.ghc-guide a{color:var(--dsw-alias-brand-primary);text-decoration:none;}', + '.ghc-guide a:hover{text-decoration:underline;}', +].join('') + /** - * Render the GitHub card. `summary` renders the one-liner the Plugins page - * places under the card's title (the description plus the token state badge); - * `page` renders the token control and the save/discard row on the plugin's - * own page. The page supplies the configuration form, so the card never - * depends on a served namespace to render. + * Render the GitHub card: the one-liner the page shows under the card's title, + * or the token control on the plugin's own page. + * @param props - locale, view, and the page-supplied configuration form. + * @returns the card's React node. */ export function GithubCard(props: GithubCardProps): ReactNode { - const { t } = props - const state = props.useGithubCard((snapshot) => snapshot) + const { t, form } = props const [draft, setDraft] = useState('') - if (props.view === 'summary') { - return createElement( - 'span', - { className: 'ghc-summary' }, - createElement('span', null, t('githubDescription')), - createElement( - 'span', - { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, - state.configured ? t('tokenSet') : t('tokenUnset'), - ), - ) + const [saving, setSaving] = useState(false) + const [failed, setFailed] = useState(false) + const stored = (form?.state.value?.githubToken ?? '').trim() + const configured = stored.length > 0 + // A summary render receives no `form` (the page hands it only to the detail + // view), so it must not claim a token state it cannot read; the badge on the + // page view is the single source of that answer. + if (props.view === 'summary') return t('githubDescription') + const writable = form?.state.writable ?? false + const staged = draft.trim() + const save = async (): Promise => { + if (form === undefined || staged === '' || saving) return + setSaving(true) + setFailed(false) + let landed = false + try { + // No explicit revision: the form fences the write with the latest one it + // knows, so a save queued behind another write cannot be rejected as stale. + landed = await form.mutate([{ op: 'set', path: ['githubToken'], value: staged }]) + } catch { + landed = false + } + setSaving(false) + if (landed) setDraft('') + else setFailed(true) } - const dirty = draft.trim() !== '' - const saveLabel = state.saving ? t('saving') : t('save') return createElement( - 'div', - { className: 'ghc-card ghc-cardPage' }, - !state.writable - ? createElement('p', { className: 'ghc-readOnly', role: 'status' }, t('readOnly')) - : null, - createElement( - 'div', - { className: 'ghc-field' }, - createElement( - 'div', - { className: 'ghc-head' }, - createElement('label', { className: 'ghc-label', htmlFor: 'plugin-config-github-token' }, t('tokenLabel')), + SettingsForm, + { + labels: { + unavailable: t('unavailable'), + readOnly: t('readOnly'), + saveFailed: t('saveFailed'), + save: t('save'), + saving: t('saving'), + }, + state: { + available: form !== undefined, + writable, + dirty: staged !== '', + invalid: false, + saving, + failed, + }, + onSave: () => { void save() }, + // SettingsForm calls this only on unmount; the draft belongs to the + // component instance, so a fresh mount starts clean either way. + onDiscard: () => {}, + children: [ + createElement(SettingsSecretField, { + id: 'plugin-config-github-token', + label: t('tokenLabel'), + configured, + stateLabel: configured ? t('tokenSet') : t('tokenUnset'), + text: draft, + hint: t('tokenHint'), + disabled: !writable || saving, + onEdit: (text: string) => setDraft(text), + }), createElement( - 'span', - { className: 'ghc-badges' }, + 'div', + { className: 'ghc-guide' }, + createElement('p', null, t('guideIntro')), createElement( - 'span', - { className: state.configured ? 'ghc-badge' : 'ghc-badgeMuted' }, - state.configured ? t('tokenSet') : t('tokenUnset'), + 'ul', + null, + createElement( + 'li', + null, + t('guideClassic'), + ' ', + createElement('a', { href: 'https://github.com/settings/tokens', target: '_blank', rel: 'noreferrer noopener' }, 'github.com/settings/tokens'), + ), + createElement( + 'li', + null, + t('guideFineGrained'), + ' ', + createElement('a', { href: 'https://github.com/settings/personal-access-tokens/new', target: '_blank', rel: 'noreferrer noopener' }, 'github.com/settings/personal-access-tokens/new'), + ), ), + createElement('p', null, t('guideStorage')), ), - ), - createElement('input', { - id: 'plugin-config-github-token', - className: 'ghc-input', - type: 'password', - autoComplete: 'off', - value: draft, - disabled: !state.credentialWritable, - onChange: (event: ChangeEvent) => setDraft(event.target.value), - }), - createElement('p', { className: 'ghc-hint' }, t('tokenHint')), - ), - createElement( - 'div', - { className: 'ghc-actions' }, - state.failed ? createElement('p', { className: 'ghc-failed', role: 'status' }, t('saveFailed')) : null, - createElement( - Button, - { - variant: 'ghost', - size: 'sm', - disabled: !dirty || state.saving, - onClick: () => setDraft(''), - }, - t('discard'), - ), - createElement( - Button, - { - variant: 'primary', - size: 'sm', - disabled: !state.writable || !dirty || state.saving, - icon: state.saving - ? createElement('span', { className: 'ghc-spin' }, createElement(IconLoadingOutlineRegular, { size: 16 })) - : undefined, - onClick: async () => { - const landed = await props.submit(draft) - if (landed) setDraft('') - }, - }, - saveLabel, - ), - ), + ], + }, ) } -/** Dictionary namespace owned by this plugin. */ -export const NS = 'dsh-github' -/** - * Required services (cordis fiber inject). `settingsScope` is gone: host - * 0.1.7-alpha.1 removed it, and the Plugins page now hands the configuration - * form to the `plugins.item` entry instead. `@deepseek-ai/dsh-client-ui-plugin-manager` - * owns that slot, so it must be composed for the card to mount at all. - */ -export const inject = ['slots', 'locale', 'connection', 'remote', 'remote.credentials'] - -export interface ClientContextLike { - get(service: string): unknown - effect(disposer: () => void, label: string): void - locale: { - bind(namespace: string): (key: keyof GithubCardLocale) => string - register(namespace: string, dictionaries: Record): void - } - remote: { - $on(event: string, listener: (ref: string) => void): unknown - credentials: CredentialsApi - } - slots: { - inject(slot: string, factory: () => unknown): unknown - register(options: Record, component: unknown): unknown - } -} - -/** The `form` member the Plugins page hands a `plugins.item` entry. */ -interface PluginConfigViewProps { - readonly view: 'summary' | 'page' - readonly form?: ConfigForm | undefined -} - /** - * Mount the GitHub configuration card into the Plugins page's Official group. - * - * The form arrives per render, so the controller is rebuilt whenever the page - * supplies a different one — the page's own form owner stays authoritative and - * the card keeps no second copy of the accepted values. + * Mount the GitHub configuration card into the Plugins panel's Official group. * @param ctx - the browser plugin context. */ export function apply(ctx: ClientContextLike): void { const t = ctx.locale.bind(NS) ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-github: card dictionaries') - let github: GithubCardController | undefined - const controllerFor = (form: PluginConfigViewProps['form']): GithubCardController => { - if (github === undefined || github.formOf() !== form) { - github = new GithubCardController(form, ctx.remote.credentials) - } - return github - } - ctx.effect( - () => ctx.remote.$on('credentials/reference-updated', (ref) => github?.refreshCredential(ref)), - 'dsh-github: credential invalidations', - ) + ctx.effect(() => { + const tagId = `${NS}/card.css` + if (document.querySelector(`style[data-plugin-css="${tagId}"]`) !== null) return () => {} + const tag = document.createElement('style') + tag.dataset.plugin = NS + tag.dataset.pluginCss = tagId + tag.textContent = CARD_CSS + document.head.appendChild(tag) + return () => { tag.remove() } + }, 'dsh-github: card styles') ctx.slots.inject('plugins.item', () => ctx.slots.register( { name: 'plugins.item', @@ -509,7 +268,6 @@ export function apply(ctx: ClientContextLike): void { order: 100, label: () => t('githubTitle'), locale: NS, - inject: () => controllerFor(github?.formOf()).inject(), }, GithubCard, )) From 53cd1b3bfa4d6922d5f117aedbefc27a1e7461d3 Mon Sep 17 00:00:00 2001 From: fishdivinity Date: Tue, 27 Oct 2026 15:21:41 +0800 Subject: [PATCH 3/5] chore: pin LF line endings for the working tree lib/ is generated by tsc and is therefore always LF, while core.autocrlf=true checks everything else out as CRLF. After every build, all 31 lib files tsc rewrote showed up as modified with no content change. The attribute makes the checkout bytes match the build output. --- .gitattributes | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..21aaa4a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# Pin the line ending the working tree gets, on every platform. +# +# `lib/` is generated by `tsc` and therefore always LF, while `core.autocrlf=true` +# on Windows checks everything else out as CRLF — so after every build, every lib +# file `tsc` rewrote showed up as modified with no content change. With `eol=lf` +# the checkout bytes match the build output and the status stays honest. +* text=auto eol=lf From 069fde37afee96ca66c13149a5e77517158e55ff Mon Sep 17 00:00:00 2001 From: fishdivinity Date: Tue, 27 Oct 2026 15:21:50 +0800 Subject: [PATCH 4/5] test(config): cover the configured token source and the volatile field --- test/config.test.ts | 13 +++++++++++++ test/credential.test.ts | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/test/config.test.ts b/test/config.test.ts index 581ade1..aae889d 100644 --- a/test/config.test.ts +++ b/test/config.test.ts @@ -1,11 +1,14 @@ import { describe, expect, it } from 'vitest' import { Config } from '../src/index.ts' +import { liveValue } from '../src/config.ts' describe('Config schema', () => { it('applies defaults for an empty object', () => { const resolved = Config({}) as Record expect(resolved.tokenSource).toBe('auto') expect(resolved.tokenRef).toBe('GITHUB_TOKEN') + // A volatile field validates to its live reference, not to the stored value. + expect(liveValue(resolved.githubToken as string | { get(): string })).toBe('') expect(resolved.autoCommit).toBe(false) expect(resolved.maxDiffChars).toBe(8000) expect(resolved.renderExcerptChars).toBe(2000) @@ -24,6 +27,16 @@ describe('Config schema', () => { expect(resolved.workspaceDir).toBeUndefined() }) + it('marks the token field volatile so the settings page can serve it', () => { + const field = (Config as unknown as { dict: Record }).dict.githubToken + expect(field?.meta.volatile).toBe(true) + }) + + it('reads a value through its live reference, or as a plain value', () => { + expect(liveValue({ get: () => 'typed' })).toBe('typed') + expect(liveValue('plain')).toBe('plain') + }) + it('fails loud on an invalid tokenSource', () => { expect(() => Config({ tokenSource: 'cloud' })).toThrowError(/tokenSource/) }) diff --git a/test/credential.test.ts b/test/credential.test.ts index 9814372..5774198 100644 --- a/test/credential.test.ts +++ b/test/credential.test.ts @@ -47,6 +47,29 @@ describe('resolveToken', () => { expect(result.ok).toBe(false) }) + it('prefers the token configured on the Plugins page over every other source', async () => { + process.env.GITHUB_TOKEN = TOKEN + const seam = { + resolve: async () => ({ value: `${TOKEN}-seam`, source: 'env' }), + } as unknown as CredentialProvider + const result = await resolveToken(seam, 'auto', 'GITHUB_TOKEN', ghRunner(), undefined, ` ${TOKEN}-page `) + expect(result.ok).toBe(true) + if (result.ok) expect(result.token).toEqual({ value: `${TOKEN}-page`, source: 'config' }) + }) + + it('falls through a blank configured token', async () => { + process.env.GITHUB_TOKEN = TOKEN + const result = await resolveToken(credentials, 'auto', 'GITHUB_TOKEN', ghRunner('fail'), undefined, ' ') + expect(result.ok).toBe(true) + if (result.ok) expect(result.token.source).toBe('env') + }) + + it('fails closed when config is pinned but no token was typed', async () => { + const result = await resolveToken(credentials, 'config', 'GITHUB_TOKEN', ghRunner(), undefined, '') + expect(result.ok).toBe(false) + if (!result.ok) expect(result.error.message).toContain('config') + }) + it('returns a structured error with guidance when nothing resolves', async () => { const result = await resolveToken(credentials, 'auto', 'GITHUB_TOKEN', ghRunner('fail')) expect(result.ok).toBe(false) From 2de4018680fb2c74be5d6b8425d7c2bb0b9359e5 Mon Sep 17 00:00:00 2001 From: fishdivinity Date: Tue, 27 Oct 2026 15:21:51 +0800 Subject: [PATCH 5/5] docs: document the githubToken field in all five READMEs --- CHANGELOG.md | 5 +++++ README-es.md | 5 +++-- README-hi.md | 5 +++-- README-pt.md | 5 +++-- README-zh.md | 5 +++-- README.md | 5 +++-- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93ec9af..8033dca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,9 +68,14 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- **`githubToken` — a token field the Plugins page can edit.** DSH 0.2.1 serves a settings namespace only for a plugin whose Config marks at least one field `.volatile()`; `dsh-github` had none, so the settings service skipped the whole namespace and the row had no editable form. The card now writes this field, and `tokenSource` gains a `config` member that `auto` tries before the credentials file, the environment, and the gh CLI. The value sits in the profile configuration as plain text; the credentials file and `gh auth login` remain the alternatives. + ### Fixed - **The shipped browser bundle registers under the package name.** `scripts/bundle-client.mjs` hardcoded `id: "dsh-github"`; DSH 0.2.1 keys client rows by package name (`@perrylink/dsh-github`), so the loader fell back to the single-resource URL and re-executed the bundle, aborting web boot with `duplicate factory registration`. The wrapper now reads `package.json.name`, and `verify:artifacts` + `test/client-bundle.test.ts` assert the registration id. +- **The GitHub card mounts again on DSH 0.2.1.** The browser half required the browser-side credentials remote, which 0.2.1 removed (`@deepseek-ai/dsh-credentials` ships no `./remote`): the client entry stayed pending — a fatal web boot in 0.2.x — and the defensive variant returned before `ctx.slots.register`, so no card appeared in the Plugins panel. It now reads the page-supplied `form` (`{ state, mutate }`), registers on `plugins.item` unconditionally, renders through `SettingsForm` / `SettingsSecretField` so themes and installed skins restyle it, and adds a short guide to both GitHub token pages. ## [0.7.18] - 2026-10-05 diff --git a/README-es.md b/README-es.md index dc24086..0b0f42f 100644 --- a/README-es.md +++ b/README-es.md @@ -172,12 +172,13 @@ created pull request #7: https://github.com/o/r/pull/7 (main ← feat/shiny) ## Configuración -Todos los ajustes son campos `Config` de Schemastery (modificables desde cordis.yml). Una anulación dirigida por id reemplaza toda la fila — vuelve a indicar cada clave que necesites. `cordis.patch.yml` documenta cada clave en línea. En la GUI, la **tarjeta de configuración de la página Plugins** (grupo Official) lee `tokenRef` del propio formulario de configuración de la entrada — el host `0.1.7-alpha.1` eliminó el enlace `ctx.settingsScope` y la costura de registro de namespaces que había detrás, así que la tarjeta ya no posee un namespace de configuración. El token de GitHub no es un campo de configuración: la tarjeta informa si la credencial referenciada está puesta y la escribe mediante el archivo de credenciales, que es de donde la resuelve la mitad host. +Todos los ajustes son campos `Config` de Schemastery (modificables desde cordis.yml). Una anulación dirigida por id reemplaza toda la fila — vuelve a indicar cada clave que necesites. `cordis.patch.yml` documenta cada clave en línea. En la GUI, la **tarjeta de configuración de la página Plugins** (grupo Official) lee `tokenRef` del propio formulario de configuración de la entrada — el host `0.1.7-alpha.1` eliminó el enlace `ctx.settingsScope` y la costura de registro de namespaces que había detrás, así que la tarjeta ya no posee un namespace de configuración. El token en sí es el campo `githubToken` de la entrada: la tarjeta lo escribe ahí y la mitad host lo resuelve antes que el archivo de credenciales, el entorno y el CLI gh. | Clave | Por defecto | Significado | |---|---|---| -| `tokenSource` | `auto` | `auto` (credenciales → env → gh) o uno de `credentials` / `env` / `gh` | +| `tokenSource` | `auto` | `auto` (campo de la página → credenciales → env → gh) o uno de `config` / `credentials` / `env` / `gh` | | `tokenRef` | `GITHUB_TOKEN` | Referencia de la capa de credenciales / nombre de la variable de entorno | +| `githubToken` | — | Token guardado desde la página Plugins; texto plano en la configuración del perfil, se usa primero mientras no esté vacío | | `defaultOwnerRepo` | — | `owner/repo` de respaldo cuando una llamada no indica ninguno y git no tiene origen | | `autoCommit` | `false` | Si `/pr create` puede indicar al modelo que haga commit+push primero | | `maxDiffChars` | `8000` | Límite de caracteres para los diffs de PR leídos en las revisiones | diff --git a/README-hi.md b/README-hi.md index 2416e26..6440ce9 100644 --- a/README-hi.md +++ b/README-hi.md @@ -172,12 +172,13 @@ created pull request #7: https://github.com/o/r/pull/7 (main ← feat/shiny) ## कॉन्फ़िगरेशन -सभी tunables Schemastery `Config` fields हैं (cordis.yml से बदले जा सकते हैं)। एक id-लक्षित override पूरी row को बदल देता है — जो key आपको चाहिए उसे दोबारा लिखें। `cordis.patch.yml` हर key को inline दस्तावेज़ित करता है। GUI में, **Plugins पेज settings card** (Official समूह) `tokenRef` उस entry के अपने configuration form से पढ़ता है — `0.1.7-alpha.1` host ने `ctx.settingsScope` binding और उसके पीछे का namespace-registration seam हटा दिया, इसलिए कार्ड अब कोई settings namespace नहीं रखता। GitHub token configuration field नहीं है: कार्ड बताता है कि referenced credential सेट है या नहीं, और उसे credentials फ़ाइल के ज़रिए लिखता है — host half वहीं से resolve करता है। +सभी tunables Schemastery `Config` fields हैं (cordis.yml से बदले जा सकते हैं)। एक id-लक्षित override पूरी row को बदल देता है — जो key आपको चाहिए उसे दोबारा लिखें। `cordis.patch.yml` हर key को inline दस्तावेज़ित करता है। GUI में, **Plugins पेज settings card** (Official समूह) `tokenRef` उस entry के अपने configuration form से पढ़ता है — `0.1.7-alpha.1` host ने `ctx.settingsScope` binding और उसके पीछे का namespace-registration seam हटा दिया, इसलिए कार्ड अब कोई settings namespace नहीं रखता। token स्वयं उस entry का `githubToken` field है: कार्ड उसे वहीं लिखता है, और host half उसे credentials फ़ाइल, environment और gh CLI से पहले resolve करता है। | कुंजी | डिफ़ॉल्ट | अर्थ | |---|---|---| -| `tokenSource` | `auto` | `auto` (credentials → env → gh) या `credentials` / `env` / `gh` में से कोई एक | +| `tokenSource` | `auto` | `auto` (पेज field → credentials → env → gh) या `config` / `credentials` / `env` / `gh` में से कोई एक | | `tokenRef` | `GITHUB_TOKEN` | Credential-seam reference / environment-variable नाम | +| `githubToken` | — | Plugins पेज से सहेजा गया token; profile configuration में plain text, खाली न होने पर पहले इस्तेमाल होता है | | `defaultOwnerRepo` | — | जब कोई call कोई नाम न दे और git के पास कोई origin न हो तो Fallback `owner/repo` | | `autoCommit` | `false` | क्या `/pr create` model को पहले commit+push करने का निर्देश दे सकता है | | `maxDiffChars` | `8000` | reviews में पढ़े जाने वाले PR diffs की character सीमा | diff --git a/README-pt.md b/README-pt.md index 6ae151c..0ff5c46 100644 --- a/README-pt.md +++ b/README-pt.md @@ -172,12 +172,13 @@ created pull request #7: https://github.com/o/r/pull/7 (main ← feat/shiny) ## Configuração -Todos os ajustes são campos `Config` do Schemastery (modificáveis a partir do cordis.yml). Uma substituição direcionada por id troca toda a linha — redeclare cada chave de que você precisa. O `cordis.patch.yml` documenta cada chave em linha. Na GUI, o **cartão de configurações da página Plugins** (grupo Official) lê `tokenRef` do próprio formulário de configuração da entrada — o host `0.1.7-alpha.1` removeu a vinculação `ctx.settingsScope` e a costura de registro de namespace por trás dela, então o cartão não possui mais um namespace de configuração. O token do GitHub não é um campo de configuração: o cartão informa se a credencial referenciada está definida e a grava pelo arquivo de credenciais, que é de onde a metade host a resolve. +Todos os ajustes são campos `Config` do Schemastery (modificáveis a partir do cordis.yml). Uma substituição direcionada por id troca toda a linha — redeclare cada chave de que você precisa. O `cordis.patch.yml` documenta cada chave em linha. Na GUI, o **cartão de configurações da página Plugins** (grupo Official) lê `tokenRef` do próprio formulário de configuração da entrada — o host `0.1.7-alpha.1` removeu a vinculação `ctx.settingsScope` e a costura de registro de namespace por trás dela, então o cartão não possui mais um namespace de configuração. O token em si é o campo `githubToken` da entrada: o cartão o grava ali e a metade host o resolve antes do arquivo de credenciais, do ambiente e do CLI gh. | Chave | Padrão | Significado | |---|---|---| -| `tokenSource` | `auto` | `auto` (credenciais → ambiente → gh) ou um de `credentials` / `env` / `gh` | +| `tokenSource` | `auto` | `auto` (campo da página → credenciais → ambiente → gh) ou um de `config` / `credentials` / `env` / `gh` | | `tokenRef` | `GITHUB_TOKEN` | Referência da camada de credenciais / nome da variável de ambiente | +| `githubToken` | — | Token salvo pela página Plugins; texto puro na configuração do perfil, usado primeiro enquanto não estiver vazio | | `defaultOwnerRepo` | — | Fallback `owner/repo` quando uma chamada não nomeia nenhum e o git não tem origin | | `autoCommit` | `false` | Se `/pr create` pode instruir o modelo a fazer commit+push primeiro | | `maxDiffChars` | `8000` | Limite de caracteres para diffs de PR lidos nas revisões | diff --git a/README-zh.md b/README-zh.md index 17ff77f..ae61569 100644 --- a/README-zh.md +++ b/README-zh.md @@ -174,12 +174,13 @@ created pull request #7: https://github.com/o/r/pull/7 (main ← feat/shiny) ## 配置 -所有可调项都是 Schemastery `Config` 字段(可从 cordis.yml 修改)。以 id 定位的覆盖会替换整行 —— 需要重新声明你所需的每个键。`cordis.patch.yml` 逐键内联说明。在图形界面中,**Plugins 页设置卡**(Official 组)从该条目自己的配置表单读取 `tokenRef`:`0.1.7-alpha.1` 宿主已删除 `ctx.settingsScope` 绑定及其背后的命名空间注册缝,卡片因此不再拥有设置命名空间。GitHub 令牌根本不是配置字段:卡片只报告所引用凭证是否已配置,并通过凭证文件写入它——宿主半部正是从那里解析的。 +所有可调项都是 Schemastery `Config` 字段(可从 cordis.yml 修改)。以 id 定位的覆盖会替换整行 —— 需要重新声明你所需的每个键。`cordis.patch.yml` 逐键内联说明。在图形界面中,**Plugins 页设置卡**(Official 组)从该条目自己的配置表单读取 `tokenRef`:`0.1.7-alpha.1` 宿主已删除 `ctx.settingsScope` 绑定及其背后的命名空间注册缝,卡片因此不再拥有设置命名空间。令牌本身就是该条目的 `githubToken` 字段:卡片写到这里,宿主半部按「页面字段 → 凭证文件 → 环境变量 → gh」的顺序解析。 | 键 | 默认值 | 含义 | |---|---|---| -| `tokenSource` | `auto` | `auto`(credentials → env → gh)或指定 `credentials` / `env` / `gh` | +| `tokenSource` | `auto` | `auto`(页面字段 → credentials → env → gh)或指定 `config` / `credentials` / `env` / `gh` | | `tokenRef` | `GITHUB_TOKEN` | credentials seam 引用名 / 环境变量名 | +| `githubToken` | — | 从插件页保存的令牌;以明文存于 profile 配置,非空时优先使用 | | `defaultOwnerRepo` | — | 调用未指定且 git 无 origin 时的兜底 `owner/repo` | | `autoCommit` | `false` | `/pr create` 是否允许指示模型先 commit+push | | `maxDiffChars` | `8000` | 审查读取 PR diff 的字符数上限 | diff --git a/README.md b/README.md index fcaa5d4..4311db1 100644 --- a/README.md +++ b/README.md @@ -174,12 +174,13 @@ created pull request #7: https://github.com/o/r/pull/7 (main ← feat/shiny) ## Configuration -All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline. In the GUI, the **Plugins page settings card** (Official group) reads `tokenRef` from the entry's own configuration form — the `0.1.7-alpha.1` host removed the `ctx.settingsScope` binding and the namespace-registration seam behind it, so the card no longer owns a settings namespace. The GitHub token is not a configuration field at all: the card reports whether the referenced credential is set and writes it through the credentials file, which is where the host half resolves it. +All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. `cordis.patch.yml` documents each key inline. In the GUI, the **Plugins page settings card** (Official group) reads `tokenRef` from the entry's own configuration form — the `0.1.7-alpha.1` host removed the `ctx.settingsScope` binding and the namespace-registration seam behind it, so the card no longer owns a settings namespace. The token itself is the entry's `githubToken` field: the card writes it there, and the host half resolves it ahead of the credentials file, the environment, and the gh CLI. | Key | Default | Meaning | |---|---|---| -| `tokenSource` | `auto` | `auto` (credentials → env → gh) or one of `credentials` / `env` / `gh` | +| `tokenSource` | `auto` | `auto` (page field → credentials → env → gh) or one of `config` / `credentials` / `env` / `gh` | | `tokenRef` | `GITHUB_TOKEN` | Credential-seam reference / environment-variable name | +| `githubToken` | — | Token saved from the Plugins page; plain text in the profile configuration, tried first while non-empty | | `defaultOwnerRepo` | — | Fallback `owner/repo` when a call names none and git has no origin | | `autoCommit` | `false` | Whether `/pr create` may instruct the model to commit+push first | | `maxDiffChars` | `8000` | Character cap for PR diffs read into reviews |