dsh-github-copilot 0.4.0-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/AGENTS.md +233 -0
  2. package/CONTRIBUTING.md +46 -0
  3. package/LICENSE +21 -0
  4. package/README.md +365 -0
  5. package/README.zh.md +376 -0
  6. package/SECURITY.md +29 -0
  7. package/cordis.patch.yml +16 -0
  8. package/deployment-baseline.json +752 -0
  9. package/docs/agent-readiness.md +95 -0
  10. package/docs/images/copilot-auth-card-signed-in.png +0 -0
  11. package/docs/images/copilot-device-code-copy.png +0 -0
  12. package/docs/images/copilot-model-freshness.png +0 -0
  13. package/docs/images/copilot-model-refreshing.png +0 -0
  14. package/docs/images/copilot-provider-authorization.png +0 -0
  15. package/docs/images/copilot-provider-entry.png +0 -0
  16. package/docs/images/github-copilot-auth-flow.gif +0 -0
  17. package/docs/model-compatibility-acceptance.md +46 -0
  18. package/docs/npm-distribution.md +134 -0
  19. package/docs/session-search-routing.md +53 -0
  20. package/docs/single-route-migration.md +115 -0
  21. package/lib/client.js +7153 -0
  22. package/lib/client.js.map +1 -0
  23. package/lib/index.js +5384 -0
  24. package/lib/remote.js +162 -0
  25. package/lib/routed-web.js +80 -0
  26. package/lib/search-routing-pFLux0W7.js +763 -0
  27. package/lib/types/account-model-auth.d.ts +15 -0
  28. package/lib/types/account-model-catalog.d.ts +67 -0
  29. package/lib/types/account-model-source.d.ts +85 -0
  30. package/lib/types/authorization-controller.d.ts +100 -0
  31. package/lib/types/client.d.ts +106 -0
  32. package/lib/types/compact-account.d.ts +42 -0
  33. package/lib/types/compatibility.d.ts +17 -0
  34. package/lib/types/config.d.ts +42 -0
  35. package/lib/types/content-file.d.ts +10 -0
  36. package/lib/types/copilot-auth.d.ts +23 -0
  37. package/lib/types/copilot-grant.d.ts +11 -0
  38. package/lib/types/copilot-identity.d.ts +6 -0
  39. package/lib/types/copilot-request.d.ts +11 -0
  40. package/lib/types/current-provider.d.ts +59 -0
  41. package/lib/types/deepseek-search-fallback.d.ts +11 -0
  42. package/lib/types/failure.d.ts +38 -0
  43. package/lib/types/http.d.ts +48 -0
  44. package/lib/types/index.d.ts +39 -0
  45. package/lib/types/migration-status.d.ts +50 -0
  46. package/lib/types/model-protocol.d.ts +31 -0
  47. package/lib/types/pi-provider-bridge.d.ts +22 -0
  48. package/lib/types/plan.d.ts +148 -0
  49. package/lib/types/preview-provider.d.ts +35 -0
  50. package/lib/types/preview-route.d.ts +63 -0
  51. package/lib/types/probe.d.ts +39 -0
  52. package/lib/types/reasoning-presentation.d.ts +55 -0
  53. package/lib/types/remote.d.ts +151 -0
  54. package/lib/types/responses-reasoning-text.d.ts +24 -0
  55. package/lib/types/responses-reasoning.d.ts +7 -0
  56. package/lib/types/route-ownership.d.ts +70 -0
  57. package/lib/types/routed-web.d.ts +38 -0
  58. package/lib/types/search-backend.d.ts +16 -0
  59. package/lib/types/search-routing.d.ts +43 -0
  60. package/lib/types/serialize.d.ts +109 -0
  61. package/lib/types/sse.d.ts +28 -0
  62. package/lib/types/temporary-models.d.ts +25 -0
  63. package/lib/types/tool-schema-compat.d.ts +17 -0
  64. package/lib/types/traditional-search.d.ts +17 -0
  65. package/lib/types/types.d.ts +69 -0
  66. package/lib/types/usage.d.ts +26 -0
  67. package/lib/types/watchdog.d.ts +22 -0
  68. package/lib/types/web-delegate.d.ts +12 -0
  69. package/lib/types/web-search-routing-card.d.ts +10 -0
  70. package/lib/types/web-search-routing-config.d.ts +16 -0
  71. package/lib/types/wire-anthropic.d.ts +37 -0
  72. package/lib/types/wire.d.ts +56 -0
  73. package/lib/web-delegate.js +9 -0
  74. package/package.json +200 -0
  75. package/scripts/check-search-composition.mjs +191 -0
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Failure classification for the inline wire path. The codes must land in
3
+ * the harness vocabulary dsh-llm-retry understands (AUTH, RATE_LIMIT,
4
+ * INVALID_REQUEST, SERVER, TIMEOUT, TRANSPORT, QUOTA,
5
+ * CONTEXT_WINDOW_EXCEEDED, UNKNOWN) so the standard retry policy applies.
6
+ * Also owns the finish-chunk constructors the two wires share.
7
+ * @module dsh-github-copilot/failure
8
+ */
9
+ import type { LlmFailure, StreamChunk } from '@deepseek-ai/dsh-llm';
10
+ /**
11
+ * Classify a non-OK HTTP response into the harness failure vocabulary.
12
+ * @param status - the HTTP status code.
13
+ * @param retryAfterMs - optional provider-requested delay in milliseconds.
14
+ * @param requestId - optional provider request id for diagnostics.
15
+ * @param apiLabel - the API family named in the diagnostic, e.g. `Messages API`.
16
+ * @returns the failure object for a finish chunk.
17
+ */
18
+ export declare function classifyHttpStatus(status: number, retryAfterMs?: number, requestId?: string, apiLabel?: string): LlmFailure;
19
+ /**
20
+ * Parse an HTTP `Retry-After` header value into milliseconds. Only a
21
+ * non-negative seconds integer is accepted; an HTTP-date or any other value
22
+ * yields `undefined` rather than a `NaN` delay.
23
+ * @param retryAfter - the raw header value, or `null` when absent.
24
+ * @returns the delay in milliseconds, or `undefined`.
25
+ */
26
+ export declare function parseRetryAfterMs(retryAfter: string | null): number | undefined;
27
+ /**
28
+ * Classify a transport-level error (fetch throw, timeout, malformed body)
29
+ * into the harness failure vocabulary.
30
+ * @param error - the thrown value.
31
+ * @returns the failure object for a finish chunk.
32
+ */
33
+ export declare function classifyWireError(error: unknown): LlmFailure;
34
+ /** The finish chunk for any failure; the generator never throws it. */
35
+ export declare function errorFinish(failure: LlmFailure): StreamChunk;
36
+ /** The finish chunk for a caller-aborted request. */
37
+ export declare function abortedFinish(): StreamChunk;
38
+ //# sourceMappingURL=failure.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared HTTP plumbing for the capability probe and the inline wires:
3
+ * bounded response reading, caller-cancellation races for preflight steps,
4
+ * and the stable {@link WebError} translations. The patterns mirror the
5
+ * harness `dsh-web` package family (web-search-deepseek, model discovery) so
6
+ * every credentialed request rejects redirects before a `Location` target can
7
+ * be contacted.
8
+ * @module dsh-github-copilot/http
9
+ */
10
+ /**
11
+ * Endpoint replies larger than this are refused. The endpoint is whatever
12
+ * base URL the configuration named, so the ceiling holds on the bytes
13
+ * actually read rather than on the length the server claims.
14
+ */
15
+ export declare const MAX_RESPONSE_BYTES: number;
16
+ /**
17
+ * Read a response body with a hard byte cap, refusing one that outgrows it.
18
+ * A declared length is checked first so an honest server is turned away
19
+ * without transferring anything; the accumulated total is what actually
20
+ * enforces the bound, because a server that under-declares (or streams) tells
21
+ * us nothing up front.
22
+ * @param response - the HTTP response whose body is read to completion.
23
+ * @param url - the requested URL, named in the refusal message.
24
+ * @returns the decoded body text.
25
+ * @throws WebError `WEB_PROVIDER_ERROR` when the body exceeds the cap.
26
+ */
27
+ export declare function readBounded(response: Response, url: string): Promise<string>;
28
+ /** Whether an error is the fetch/`AbortSignal` abort signal. */
29
+ export declare function isAbortError(error: unknown): boolean;
30
+ /**
31
+ * Race a same-process asynchronous preflight (credential resolution) against
32
+ * a cancellation signal. The attached settlement handlers keep observing an
33
+ * uncooperative operation after the race is lost, so a later rejection cannot
34
+ * become unhandled.
35
+ * @param operation - the preflight promise.
36
+ * @param signal - the cancellation signal (request abort or idle watchdog).
37
+ * @returns the operation's value, or a rejection once the signal fires.
38
+ */
39
+ export declare function abortable<T>(operation: Promise<T>, signal: AbortSignal | undefined): Promise<T>;
40
+ /**
41
+ * Extract a provider error message from an error envelope whose shape varies
42
+ * by protocol and vendor: `{ error: { message } }`, `{ error: "text" }`, or
43
+ * `{ message }`. Returns `undefined` when nothing usable is present.
44
+ * @param body - the parsed non-2xx response body.
45
+ * @returns the provider message, or `undefined`.
46
+ */
47
+ export declare function providerErrorMessage(body: unknown): string | undefined;
48
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The inline web-search plugin: short-circuits agent-loop model calls on
3
+ * the `llm/stream` waterfall, injecting the server-side `web_search` tool
4
+ * into the wire request so search executes inside the model's own turn.
5
+ * The narrow gate keeps every other request on the normal adapter path.
6
+ * @module dsh-github-copilot
7
+ */
8
+ import type { Context } from '@deepseek-ai/cordis';
9
+ import type { SettingsNamespace } from '@deepseek-ai/dsh-settings';
10
+ import type { InlineConfig } from './config.ts';
11
+ export { COPILOT_HOSTED_SEARCH_PROVIDER_ID, GITHUB_COPILOT_HOSTED_SEARCH_PROVIDER_ID, } from './traditional-search.ts';
12
+ /** Cordis plugin name used by loader diagnostics. */
13
+ export declare const name = "github-copilot";
14
+ /**
15
+ * Bootstrap dependency. The integration itself is mounted below only after
16
+ * every service in {@link integrationInject}, including authorization, is
17
+ * active.
18
+ */
19
+ export declare const inject: string[];
20
+ /** Settings namespace carrying this plugin's section. */
21
+ export declare const GITHUB_COPILOT_SETTINGS_NAMESPACE: SettingsNamespace;
22
+ /** Schema of the plugin's settings section, exported for composition consumers. */
23
+ export { Config } from './config.ts';
24
+ export type { InlineConfig } from './config.ts';
25
+ export { NO_DEFAULT_SEARCH_PROVIDER, WEB_SEARCH_ROUTING_SETTINGS_NAMESPACE, WebSearchRoutingConfigSchema, } from './web-search-routing-config.ts';
26
+ export type { WebSearchRoutingConfig } from './web-search-routing-config.ts';
27
+ export { assertDshCompatibility, DSH_COMPATIBILITY } from './compatibility.ts';
28
+ export { GITHUB_COPILOT_CREDENTIAL_KEY, GitHubCopilotAuthorizationController, describeGitHubCopilotProviderProfile, ensureGitHubCopilotProviderProfile, LLM_PI_AI_SETTINGS_NAMESPACE, } from './authorization-controller.ts';
29
+ export type { AuthorizationNoticeView, GitHubCopilotAuthorizationPhase, GitHubCopilotAuthorizationView, GitHubCopilotRouteView, } from './authorization-controller.ts';
30
+ /**
31
+ * Register the inline short-circuit. The plan (candidates plus probe
32
+ * verdict) follows the settings section; the listener reads the CURRENT
33
+ * plan and config per request.
34
+ * @param ctx - context whose `llm` events and `systemPrompt` receive the
35
+ * registrations; both are effect-scoped and unregister on dispose.
36
+ * @param config - the composition entry config, used as the settings base layer.
37
+ */
38
+ export declare function apply(ctx: Context, config: InlineConfig): void;
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,50 @@
1
+ /** Read-only, synchronous evidence for an independently authorized Ops migration. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ export interface MigrationSelection {
4
+ readonly provider: string;
5
+ readonly model: string;
6
+ readonly reasoningEffort?: string;
7
+ }
8
+ export interface MigrationSession {
9
+ readonly id: string;
10
+ readonly status: 'idle' | 'running';
11
+ readonly effectiveSelection: MigrationSelection | null;
12
+ readonly selectionSource: 'pending' | 'request-header' | 'default' | 'unknown';
13
+ /** Latest recorded request config for running Agents, not proof of an in-flight model call. */
14
+ readonly activeRequestSelection: MigrationSelection | null;
15
+ }
16
+ /** Loaded plugin identity is not Desktop/Core byte attestation. Cold histories are not inspected. */
17
+ export interface GitHubCopilotMigrationStatus {
18
+ readonly plugin: {
19
+ readonly name: string;
20
+ readonly version: string;
21
+ };
22
+ readonly protocolVersion: 1;
23
+ readonly historyScope: 'live-agents-only';
24
+ readonly observedAt: number;
25
+ readonly capabilities: {
26
+ readonly agentsList: boolean;
27
+ readonly sessionProjections: boolean;
28
+ readonly settingsCas: boolean;
29
+ readonly providerRegistry: boolean;
30
+ readonly defaultSelection: boolean;
31
+ };
32
+ readonly complete: {
33
+ readonly sessions: boolean;
34
+ readonly defaultSelection: boolean;
35
+ readonly routes: boolean;
36
+ };
37
+ readonly defaultSelection: MigrationSelection | null;
38
+ readonly sessions: readonly MigrationSession[];
39
+ readonly routes: {
40
+ readonly nativeConfigured: boolean | null;
41
+ readonly nativeRegistered: boolean | null;
42
+ readonly managedRegistered: boolean | null;
43
+ };
44
+ }
45
+ /**
46
+ * Observe only public live leaves in one synchronous stack, without writes or network.
47
+ * This is not a cross-namespace transaction; callers must recheck immediately before CAS.
48
+ */
49
+ export declare function migrationStatus(ctx: Context): GitHubCopilotMigrationStatus;
50
+ //# sourceMappingURL=migration-status.d.ts.map
@@ -0,0 +1,31 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type { Api, Model } from '@earendil-works/pi-ai';
3
+ /** Public facts from this plugin's pi-ai dependency, not a claim about another Core copy. */
4
+ export interface CopilotModelFacts {
5
+ readonly id: string;
6
+ readonly provider: string;
7
+ readonly api: string;
8
+ readonly name: string;
9
+ readonly baseUrl: string;
10
+ readonly contextWindow: number;
11
+ readonly maxTokens: number;
12
+ readonly input: readonly ('text' | 'image')[];
13
+ readonly reasoning: boolean;
14
+ readonly supportsReasoningOff: boolean;
15
+ readonly reasoningEfforts: Readonly<Record<string, string>>;
16
+ readonly headers?: Readonly<Record<string, string | null>>;
17
+ }
18
+ export interface CopilotCatalogSnapshot {
19
+ readonly models: readonly CopilotModelFacts[];
20
+ /** True only for models whose actual native provider is built by this plugin. */
21
+ readonly authoritative: boolean;
22
+ }
23
+ /** Project only public leaves and the same pi library's supported wire efforts. */
24
+ export declare function projectModelFacts(model: Model<Api>): CopilotModelFacts;
25
+ /** Stock Core owns its own catalog; local metadata must not retire corrections on its behalf. */
26
+ export declare function readCopilotCatalog(_ctx: Context): CopilotCatalogSnapshot;
27
+ /** The preview uses this exact pi provider instance family, so local model facts are authoritative there. */
28
+ export declare function readPreviewCatalog(): CopilotCatalogSnapshot;
29
+ /** Scope optional preview contributions to this plugin's successfully mounted route service. */
30
+ export declare function isPluginPreviewProvider(ctx: Context, provider: string): boolean;
31
+ //# sourceMappingURL=model-protocol.d.ts.map
@@ -0,0 +1,22 @@
1
+ import type { Provider, AssistantMessageEventStream } from '@earendil-works/pi-ai';
2
+ import type { ResolvedPiAiProviderProfile } from '@deepseek-ai/dsh-llm-pi-ai';
3
+ export type CoreCompatibleProvider = ResolvedPiAiProviderProfile['piProvider'];
4
+ export type SimpleNativeProvider = Pick<Provider, 'id' | 'name' | 'baseUrl' | 'headers' | 'auth' | 'getModels' | 'filterModels' | 'streamSimple'>;
5
+ type CoreStream = ReturnType<CoreCompatibleProvider['streamSimple']>;
6
+ type PublicCoreStream = Pick<CoreStream, keyof CoreStream>;
7
+ type PublicNativeStream = Pick<AssistantMessageEventStream, keyof AssistantMessageEventStream>;
8
+ type Assert<Condition extends true> = Condition;
9
+ /** Compile-time, bidirectional proof; a future real public event change must fail this gate. */
10
+ export type PiStreamPublicCompatibility = [
11
+ Assert<PublicNativeStream extends PublicCoreStream ? true : false>,
12
+ Assert<PublicCoreStream extends PublicNativeStream ? true : false>
13
+ ];
14
+ /** Retain the same stream object after proving its public surface; only SDK-private nominal identity differs. */
15
+ export declare function coreEventStream(stream: AssistantMessageEventStream): CoreStream;
16
+ /**
17
+ * The published Core adapter consumes streamSimple. Do not pretend its older
18
+ * protocol-specific clients are interchangeable with a newer SDK's clients.
19
+ */
20
+ export declare function coreProviderView(provider: SimpleNativeProvider): CoreCompatibleProvider;
21
+ export {};
22
+ //# sourceMappingURL=pi-provider-bridge.d.ts.map
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Search-plan resolution: which protocol and endpoint native search runs
3
+ * through. The initiating Agent's captured chat route (selection plus the
4
+ * `llm-pi-ai` settings section) is detected and probed — its own protocol
5
+ * when that can search. The {@link SearchPlan} class owns the probe lifecycle so
6
+ * `available()` stays synchronous while the verdict lands in the background.
7
+ * @module dsh-github-copilot/plan
8
+ */
9
+ import type { Context } from '@deepseek-ai/cordis';
10
+ import type { ProbeOutcome } from './probe.ts';
11
+ import type { CurrentChatRoute } from './current-provider.ts';
12
+ /** The two search-capable wire protocols this package speaks. */
13
+ export type SearchProtocol = 'openai-responses' | 'anthropic-messages';
14
+ /** Credential record that owns GitHub Copilot OAuth state and refresh. */
15
+ export declare const GITHUB_COPILOT_CREDENTIAL_KEY = "llm-pi-ai/github-copilot";
16
+ /** Default `anthropic-version` header value. */
17
+ export declare const DEFAULT_API_VERSION = "2023-06-01";
18
+ /**
19
+ * The server-side Responses web tool spellings. The standard `web_search`
20
+ * is the preferred Copilot spelling; `web_search_2025_08_26` is retained as
21
+ * a probe fallback for provider-side protocol variation.
22
+ */
23
+ export type ResponsesWebSearchToolType = 'web_search' | 'web_search_2025_08_26';
24
+ /** Standard server-side web search tool type (OpenAI/DeepSeek official). */
25
+ export declare const WEB_SEARCH_TOOL_TYPE: ResponsesWebSearchToolType;
26
+ /**
27
+ * Versioned Responses spelling retained as a capability-probe fallback.
28
+ */
29
+ export declare const RESPONSES_WEB_SEARCH_TOOL_TYPE: ResponsesWebSearchToolType;
30
+ /** Anthropic server-side web search tool type (versioned). */
31
+ export declare const ANTHROPIC_WEB_SEARCH_TOOL_TYPE = "web_search_20250305";
32
+ /**
33
+ * Fully defaulted endpoint facts one search (or probe) operation runs with.
34
+ * Every field is resolved once at plan build time so the adapters never fall
35
+ * back mid-operation.
36
+ */
37
+ export interface SearchPlanCandidate {
38
+ readonly protocol: SearchProtocol;
39
+ /** Endpoint base; `/responses` or `/messages` is appended by the adapter. */
40
+ readonly baseURL: string;
41
+ readonly model: string;
42
+ /** Credential reference resolved through the credentials seam. */
43
+ readonly apiKeyEnv: string;
44
+ /** `anthropic-version` header value (anthropic-messages only). */
45
+ readonly apiVersion: string;
46
+ /** Static provider/model headers inherited from pi-ai's catalog. */
47
+ readonly headers?: Readonly<Record<string, string | null>>;
48
+ /**
49
+ * The Responses web tool spelling this candidate serves with (probe-verified;
50
+ * openai-responses only). The probe may settle on the fallback spelling, in
51
+ * which case the chosen candidate carries the verified one.
52
+ */
53
+ readonly webSearchToolType?: ResponsesWebSearchToolType;
54
+ }
55
+ /** The plugin-config fields the plan reads; `apply` projects the full section onto this. */
56
+ export interface PlanConfig {
57
+ /** Whether a live capability probe verifies each candidate before use. */
58
+ readonly probe: boolean;
59
+ /** Bound on one probe request, in milliseconds. */
60
+ readonly probeTimeoutMs: number;
61
+ }
62
+ /**
63
+ * Normalize an anthropic-messages base so appending `/messages` reaches the
64
+ * Messages endpoint under either base convention: the SDK-style root
65
+ * (`https://api.anthropic.com` → `/v1/messages`) and the v1-included base
66
+ * (`https://api.deepseek.com/anthropic/v1` → `/messages`).
67
+ * @param baseURL - the configured or catalog base.
68
+ * @returns the base `/messages` is appended to.
69
+ */
70
+ export declare function ensureV1Base(baseURL: string): string;
71
+ /**
72
+ * Return the selected Copilot model's native search protocol. No endpoint or
73
+ * cross-provider sibling is guessed.
74
+ * @param route - the current chat route facts.
75
+ * @returns the single native candidate, or none for an unsupported route.
76
+ */
77
+ export declare function siblingCandidates(route: CurrentChatRoute): readonly {
78
+ protocol: SearchProtocol;
79
+ baseURL: string;
80
+ }[];
81
+ /**
82
+ * Resolve the candidate set for one plan from the current chat route. An
83
+ * empty result means the plugin auto-disables — nothing to probe, nothing to
84
+ * register.
85
+ * @param ctx - plugin context for route detection.
86
+ * @param config - the currently authoritative plan config.
87
+ * @returns the candidates in probe order.
88
+ */
89
+ export declare function resolveCandidates(ctx: Context, _config: PlanConfig): readonly SearchPlanCandidate[];
90
+ /**
91
+ * Build only from the route captured by the caller, without rereading selection.
92
+ * @param route - operation-local route facts.
93
+ * @returns native Copilot candidates, or none without supported facts.
94
+ */
95
+ export declare function candidatesForRoute(route: CurrentChatRoute | undefined): readonly SearchPlanCandidate[];
96
+ /** Lifecycle state of one search plan. */
97
+ export type SearchPlanStatus = 'probing' | 'ready' | 'failed';
98
+ /**
99
+ * One candidate set plus its probe lifecycle. The probe runs in the
100
+ * background so plugin load never blocks on a provider round-trip;
101
+ * `available()` stays synchronous and `settle()` awaits the verdict. A
102
+ * failed plan keeps its reason so the first search (or tool call) surfaces
103
+ * the auto-disable diagnostic instead of a bare "no provider" error.
104
+ */
105
+ export declare class SearchPlan {
106
+ private readonly probe;
107
+ /** Captured owner/proof lifetime, shared by probes and every served operation. */
108
+ readonly signal?: AbortSignal | undefined;
109
+ readonly candidates: readonly SearchPlanCandidate[];
110
+ /** Resolves when the probe verdict (or the immediate decision) lands. */
111
+ readonly settled: Promise<void>;
112
+ private status;
113
+ private chosen;
114
+ private reason;
115
+ /**
116
+ * @param candidates - the candidates in probe order; empty disables the plan.
117
+ * @param probe - verifies one candidate; called sequentially until one passes.
118
+ * @param probeEnabled - when false the first candidate is trusted outright.
119
+ * @param signal - captured owner/proof cancellation, retained through final HTTP.
120
+ */
121
+ constructor(candidates: readonly SearchPlanCandidate[], probe: (candidate: SearchPlanCandidate) => Promise<ProbeOutcome>, probeEnabled: boolean,
122
+ /** Captured owner/proof lifetime, shared by probes and every served operation. */
123
+ signal?: AbortSignal | undefined);
124
+ /** Probe candidates in order; the first supported verdict wins. */
125
+ private runProbe;
126
+ /**
127
+ * Cheap synchronous usability check for the listener gate. While probing
128
+ * the plan is PROVISIONALLY available — the first gated request may enter
129
+ * and await {@link settle} — so the probe verdict and the stream start in
130
+ * parallel; only a failed (or candidate-less) plan is unavailable and keeps
131
+ * the request on the normal adapter path.
132
+ * @returns whether a search can currently be served.
133
+ */
134
+ available(): boolean;
135
+ /**
136
+ * Await the probe verdict and return the winning candidate.
137
+ * @returns the candidate whose probe passed (or the first, when probing is off).
138
+ * @throws WebError `WEB_PROVIDER_UNAVAILABLE` naming the auto-disable reason.
139
+ */
140
+ settle(): Promise<SearchPlanCandidate>;
141
+ /** The candidate currently serving searches, once the plan settled on one. */
142
+ chosenCandidate(): SearchPlanCandidate | undefined;
143
+ /** The auto-disable reason, once a probe failed (or no candidate existed). */
144
+ failureReason(): string | undefined;
145
+ }
146
+ /** Whether two candidate sets are identical (skips re-probing on no-op settings changes). */
147
+ export declare function sameCandidates(left: readonly SearchPlanCandidate[], right: readonly SearchPlanCandidate[]): boolean;
148
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1,35 @@
1
+ import type { Api, Model, StreamOptions } from '@earendil-works/pi-ai';
2
+ import type { AccountModelApi, AccountModelDescriptor } from './account-model-catalog.ts';
3
+ import type { CoreCompatibleProvider } from './pi-provider-bridge.ts';
4
+ import type { GitHubCopilotOAuthCredential } from './copilot-grant.ts';
5
+ /** Per-call authorization/lifetime checks supplied by the owning route. */
6
+ export interface PreviewProviderGuard {
7
+ readonly signal: AbortSignal;
8
+ assertActive(): void;
9
+ assertAccount(credential: GitHubCopilotOAuthCredential): void;
10
+ beforeWire(model: Model<Api>, options?: StreamOptions): Promise<{
11
+ signal: AbortSignal;
12
+ release(): void;
13
+ }>;
14
+ }
15
+ /** Guard for one selected model in an account-bound descriptor snapshot. */
16
+ export interface AccountProviderGuard extends PreviewProviderGuard {
17
+ readonly selectedModelId?: string;
18
+ assertEntitled(credential: GitHubCopilotOAuthCredential, modelId: string): void;
19
+ }
20
+ /** The independent prompt limit is retained for the route's budget guard, not folded into context capacity. */
21
+ export type AccountPiModel = Model<AccountModelApi> & {
22
+ readonly maxInputTokens?: number;
23
+ readonly unmappedReasoningEfforts: readonly string[];
24
+ readonly minThinkingBudget?: number;
25
+ readonly maxThinkingBudget?: number;
26
+ };
27
+ export declare function copilotPublicHeaders(): Readonly<Record<string, string>>;
28
+ /** Materialize advertised capabilities only; model names and the local static catalog never select the API. */
29
+ export declare function accountModelFromDescriptor(descriptor: AccountModelDescriptor, baseURL: string): AccountPiModel;
30
+ /** Create a descriptor-driven, OAuth-only provider using native SDK serialization for all supported endpoints. */
31
+ export declare function createAccountProvider(descriptors: readonly AccountModelDescriptor[], guard: AccountProviderGuard, baseURL: string): {
32
+ provider: CoreCompatibleProvider;
33
+ models: readonly AccountPiModel[];
34
+ };
35
+ //# sourceMappingURL=preview-provider.d.ts.map
@@ -0,0 +1,63 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import type { PiAiProviderProfile } from '@deepseek-ai/dsh-llm-pi-ai';
3
+ import { GITHUB_COPILOT_PREVIEW_PROVIDER_ID } from './copilot-identity.ts';
4
+ import type { AccountModelLoadOptions } from './account-model-source.ts';
5
+ import type { AccountModelRejection } from './account-model-catalog.ts';
6
+ import type { InlineConfig } from './config.ts';
7
+ /** Safe request knobs; identities, model tables, endpoints and credentials are not configurable. */
8
+ export type PreviewRouteConfig = Pick<PiAiProviderProfile, 'reasoning' | 'cacheRetention' | 'transport' | 'timeoutMs' | 'websocketConnectTimeoutMs' | 'streamIdleTimeoutMs' | 'maxRequestImageBytes' | 'requestImagePixelBudget' | 'requestImageMaxBytes' | 'retryPolicy'> & Pick<InlineConfig, 'accountModelTtlMs' | 'accountModelFailureCooldownMs'> & {
9
+ readonly accountModelSettings?: () => Pick<InlineConfig, 'accountModelTtlMs' | 'accountModelFailureCooldownMs'>;
10
+ };
11
+ export interface GitHubCopilotPreviewView {
12
+ readonly provider: typeof GITHUB_COPILOT_PREVIEW_PROVIDER_ID;
13
+ readonly configured: boolean;
14
+ readonly available: boolean;
15
+ readonly correctionActive: boolean;
16
+ readonly state: 'idle' | 'loading' | 'ready' | 'stale' | 'unconfigured' | 'unavailable' | 'error' | 'disposed';
17
+ readonly models: readonly {
18
+ readonly id: string;
19
+ readonly name: string;
20
+ readonly api: string;
21
+ }[];
22
+ readonly rejected: readonly AccountModelRejection[];
23
+ readonly warnings: readonly {
24
+ readonly id: string;
25
+ readonly code: string;
26
+ }[];
27
+ readonly discoveredAt?: number;
28
+ readonly error?: string;
29
+ }
30
+ export interface GitHubCopilotPreview {
31
+ getView(): GitHubCopilotPreviewView;
32
+ /** Host-only current endpoint facts; no discovery and no credential material. */
33
+ routeFacts(modelId: string): {
34
+ readonly api: string;
35
+ readonly baseURL: string;
36
+ } | undefined;
37
+ /** Capture credential-proof continuity, independent of ordinary metadata cache TTL. */
38
+ captureSearchProof(): () => boolean;
39
+ /** Host-only credential resolution for an independent, account-scoped search request. */
40
+ resolveRequestAuth(modelId: string, signal?: AbortSignal): Promise<{
41
+ readonly apiKey: string;
42
+ readonly baseURL: string;
43
+ readonly headers: Readonly<Record<string, string>>;
44
+ }>;
45
+ /** Read stored credentials/status only; never starts native refresh or discovery. */
46
+ refresh(): Promise<GitHubCopilotPreviewView>;
47
+ /** Explicit account model discovery. May refresh native OAuth and GET /models. */
48
+ discover(options?: AccountModelLoadOptions): Promise<GitHubCopilotPreviewView>;
49
+ }
50
+ declare module '@deepseek-ai/cordis' {
51
+ interface Context {
52
+ githubCopilotPreview: GitHubCopilotPreview;
53
+ }
54
+ }
55
+ /** Register one stable account route; attach/status remain network-free. */
56
+ export declare function apply(ctx: Context, config?: PreviewRouteConfig): void;
57
+ declare const _default: {
58
+ name: string;
59
+ inject: string[];
60
+ apply: typeof apply;
61
+ };
62
+ export default _default;
63
+ //# sourceMappingURL=preview-route.d.ts.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Capability probe: one bounded operation per candidate protocol that forces
3
+ * the server-side web tool to run and checks the reply for the structured
4
+ * evidence that it did. A protocol claim is trusted only after this passes —
5
+ * several "Responses-compatible" gateways accept the `web_search` tool field
6
+ * and silently ignore it (DeepSeek documents that unknown tool types are
7
+ * ignored), which is exactly the failure mode static protocol detection
8
+ * cannot see. The probe is what makes the auto-disable decision honest.
9
+ * @module dsh-github-copilot/probe
10
+ */
11
+ import type { ResponsesWebSearchToolType, SearchPlanCandidate } from './plan.ts';
12
+ import type { ResolvedRequestAuth } from './copilot-request.ts';
13
+ /** The outcome of probing one candidate. */
14
+ export interface ProbeOutcome {
15
+ readonly supported: boolean;
16
+ /** Why the candidate failed, for the auto-disable diagnostic. */
17
+ readonly detail: string;
18
+ /**
19
+ * The Responses tool spelling the probe verified (openai-responses only).
20
+ * May differ from the candidate's primary spelling when the fallback won;
21
+ * the wire must use this verified value.
22
+ */
23
+ readonly webSearchToolType?: ResponsesWebSearchToolType;
24
+ }
25
+ /**
26
+ * Probe one candidate protocol with a bounded request sequence. The verdict is
27
+ * structural: a Responses reply must contain a `web_search_call` item and a
28
+ * Messages reply must contain a `web_search_tool_result` block; anything else
29
+ * — HTTP error, unparseable body, silent tool ignore — is "not supported".
30
+ * The timeout bounds the WHOLE probe, including credential resolution; the
31
+ * probe never throws — every failure becomes a verdict.
32
+ * @param candidate - the resolved endpoint facts to verify.
33
+ * @param resolveApiKey - resolves the candidate's credential reference.
34
+ * @param timeoutMs - bound on the whole probe.
35
+ * @param signal - optional owner lifecycle cancellation; abort forbids later attempts.
36
+ * @returns the verdict and a diagnostic detail.
37
+ */
38
+ export declare function probeCandidate(candidate: SearchPlanCandidate, resolveApiKey: (candidate: SearchPlanCandidate) => Promise<string | ResolvedRequestAuth | undefined>, timeoutMs: number, signal?: AbortSignal): Promise<ProbeOutcome>;
39
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1,55 @@
1
+ /** Plugin-owned, Step-scoped provenance; never a model route or durable message. */
2
+ export declare const ASSISTANT_ORIGIN_KEY = "github-copilot-assistant-origin";
3
+ type Dispose = () => void;
4
+ export interface AssistantOrigin {
5
+ readonly seq: number;
6
+ readonly provider: string;
7
+ readonly model: string;
8
+ }
9
+ interface OriginState {
10
+ readonly turn: number;
11
+ readonly step: number;
12
+ readonly origin: AssistantOrigin | undefined;
13
+ }
14
+ interface OriginMatch {
15
+ readonly event: unknown;
16
+ }
17
+ interface OriginContext {
18
+ readonly state?: OriginState | undefined;
19
+ readonly matches: readonly OriginMatch[];
20
+ }
21
+ interface OriginLocationData {
22
+ readonly kind: 'step';
23
+ readonly turn: number;
24
+ readonly step: number;
25
+ readonly key: typeof ASSISTANT_ORIGIN_KEY;
26
+ readonly value: AssistantOrigin;
27
+ }
28
+ /** Targetless Definition: registration rebuilds existing bindings, including cold history. */
29
+ export declare const assistantOriginDefinition: {
30
+ kind: string;
31
+ match(event: unknown): {
32
+ id: string;
33
+ role: "start" | "update";
34
+ } | null;
35
+ start(_context: OriginContext, match: OriginMatch): OriginState;
36
+ update(context: OriginContext & {
37
+ readonly state: OriginState;
38
+ }, match: OriginMatch): OriginState;
39
+ buildLocationData(context: OriginContext, scope: string, previous: OriginLocationData | null): OriginLocationData | null;
40
+ };
41
+ /** Shallow UI-only projection. Unchanged input retains its exact props identity. */
42
+ export declare function projectReasoningPresentation<Props extends object>(props: Props, origin: unknown): Props;
43
+ export interface ReasoningPresentationCapabilities {
44
+ readonly slots: unknown;
45
+ readonly uiConversation: unknown;
46
+ /** Receives stable codes only, never message text, model payloads or error bodies. */
47
+ readonly diagnostic: (code: string) => void;
48
+ }
49
+ /**
50
+ * Optional Client enhancement. The caller owns the returned disposer in its
51
+ * dependency-scoped effect; missing older-Core seams leave native UI alone.
52
+ */
53
+ export declare function installReasoningPresentation(capabilities: ReasoningPresentationCapabilities): Dispose;
54
+ export {};
55
+ //# sourceMappingURL=reasoning-presentation.d.ts.map