@ggui-ai/mcp-server 0.28.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/build-mcp.d.ts +84 -1
- package/dist/build-mcp.d.ts.map +1 -1
- package/dist/build-mcp.js +306 -3
- package/dist/console-config-routes.js +1 -1
- package/dist/console-mcp-tools-routes.d.ts +1 -1
- package/dist/console-mcp-tools-routes.d.ts.map +1 -1
- package/dist/console-mcp-tools-routes.js +1 -1
- package/dist/control-service.d.ts +1 -1
- package/dist/control-service.d.ts.map +1 -1
- package/dist/control-service.js +1 -1
- package/dist/ggui-session-channel/subscribe.d.ts.map +1 -1
- package/dist/ggui-session-channel/subscribe.js +24 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/llm-backed-negotiator.d.ts +10 -48
- package/dist/llm-backed-negotiator.d.ts.map +1 -1
- package/dist/llm-backed-negotiator.js +5 -135
- package/dist/mcp-apps-outbound.d.ts.map +1 -1
- package/dist/mcp-apps-outbound.js +7 -2
- package/dist/mcp-endpoint-routes.d.ts.map +1 -1
- package/dist/mcp-endpoint-routes.js +5 -2
- package/dist/oauth-as-routes.d.ts +3 -0
- package/dist/oauth-as-routes.d.ts.map +1 -1
- package/dist/oauth-as-routes.js +20 -13
- package/dist/oauth.d.ts +24 -18
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +42 -40
- package/dist/request-context.d.ts +19 -0
- package/dist/request-context.d.ts.map +1 -1
- package/dist/request-context.js +17 -1
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -2
- package/dist/storage.d.ts +11 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +4 -3
- package/package.json +15 -15
package/dist/index.d.ts
CHANGED
|
@@ -31,8 +31,10 @@ export type { GenerationDeps } from '@ggui-ai/mcp-server-handlers';
|
|
|
31
31
|
export { buildNoCredentialsGguiSession } from '@ggui-ai/mcp-server-handlers';
|
|
32
32
|
export { buildOpsBundleHandlers, createGguiServer, defaultHandlers, DEFAULT_CLOSE_GRACE_MS, DEFAULT_HEADERS_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_TIMEOUT_MS, } from './server.js';
|
|
33
33
|
export type { CreateGguiServerOptions, ErrorMapperResult, GguiServer, OpsBundleDeps, } from './server.js';
|
|
34
|
-
export {
|
|
35
|
-
export type {
|
|
34
|
+
export { buildLlmCaller } from './llm-backed-negotiator.js';
|
|
35
|
+
export type { BuildLlmCallerOptions } from './llm-backed-negotiator.js';
|
|
36
|
+
export { AnthropicStructuredCallError, isAnthropicStructuredCallError, } from '@ggui-ai/ui-gen/providers';
|
|
37
|
+
export type { AnthropicStructuredCallFailureKind } from '@ggui-ai/ui-gen/providers';
|
|
36
38
|
export { buildControlService, CONTROL_PATH, filterHandlersByAudience, SINGLE_CALL_OPS, } from './control-service.js';
|
|
37
39
|
export type { AudienceTag, BuildControlServiceArgs } from './control-service.js';
|
|
38
40
|
export { computeRuntimeBundleHash, insertRuntimeBundleHash, resolveHashedRuntimeBundleUrl, resolveRuntimeBundleHash, } from './runtime-bundle-hash.js';
|
|
@@ -50,6 +52,7 @@ export type { ServerInfo } from './build-mcp.js';
|
|
|
50
52
|
export { UnauthenticatedError, DEFAULT_BUILDER_APP_ID, defaultAppIdFromIdentity, } from './auth.js';
|
|
51
53
|
export { createConsoleLogger } from './logger.js';
|
|
52
54
|
export type { Logger } from './logger.js';
|
|
55
|
+
export { currentRequestUserAgent } from './request-context.js';
|
|
53
56
|
export { ChannelSessionNotFoundError, createGguiSessionChannelServer, DEFAULT_RENDER_CHANNEL_PATH, } from './ggui-session-channel.js';
|
|
54
57
|
export type { GguiSessionChannelOptions, GguiSessionChannelServer, SubscriberSink, } from './ggui-session-channel.js';
|
|
55
58
|
export { resolveStorageFromConfig } from './storage.js';
|
|
@@ -83,6 +86,8 @@ export type { GoogleLoginProviderOptions } from './oauth-providers/google.js';
|
|
|
83
86
|
export { githubLoginProvider } from './oauth-providers/github.js';
|
|
84
87
|
export type { GithubLoginProviderOptions } from './oauth-providers/github.js';
|
|
85
88
|
export { createOAuthProvidersStore } from './oauth-providers-store.js';
|
|
89
|
+
export type { OAuthConfig, OAuthStorage, AuthCodeRecord, ClientRecord } from './oauth.js';
|
|
90
|
+
export { InMemoryOAuthStorage } from './oauth.js';
|
|
86
91
|
export type { OAuthProvidersStore, OAuthProvidersStoreOptions, PutInput as OAuthProvidersStorePutInput, } from './oauth-providers-store.js';
|
|
87
92
|
export { DEFAULT_ADMIN_OAUTH_PROVIDERS_PATH, mountAdminOAuthProvidersTransport, } from './admin-oauth-providers-transport.js';
|
|
88
93
|
export type { AdminOAuthProvidersTransportOptions } from './admin-oauth-providers-transport.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAKlF,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,UAAU,EACV,aAAa,GACd,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,12 @@ export { buildOpsBundleHandlers, createGguiServer, defaultHandlers, DEFAULT_CLOS
|
|
|
35
35
|
// synthesizer). Exported so a deployment that builds its own negotiator
|
|
36
36
|
// reuses this one Anthropic structured-call implementation — and can bound
|
|
37
37
|
// it with an abort signal — instead of carrying a copy.
|
|
38
|
-
|
|
38
|
+
// The named error is the shared structured call's
|
|
39
|
+
// (`@ggui-ai/ui-gen/providers`), re-exported with its guard. Match on
|
|
40
|
+
// `isAnthropicStructuredCallError`, which holds even when a second copy
|
|
41
|
+
// of `@ggui-ai/ui-gen` is installed; `instanceof` does not.
|
|
42
|
+
export { buildLlmCaller } from './llm-backed-negotiator.js';
|
|
43
|
+
export { AnthropicStructuredCallError, isAnthropicStructuredCallError, } from '@ggui-ai/ui-gen/providers';
|
|
39
44
|
// Control plane (`/control`) — the composition that projects every
|
|
40
45
|
// `protocol`- and `ops`-tagged handler onto one anonymous-capable
|
|
41
46
|
// route with per-tool auth + confirmation gates. `createGguiServer`
|
|
@@ -73,6 +78,9 @@ export { composePreviewReservedValidator, mergeReservedValidators, } from './res
|
|
|
73
78
|
export { checkRenderSchemaCompat, DEFAULT_SCHEMA_COMPAT_MODE, hasErrorFinding, SchemaCompatError, } from './schema-compat.js';
|
|
74
79
|
export { UnauthenticatedError, DEFAULT_BUILDER_APP_ID, defaultAppIdFromIdentity, } from './auth.js';
|
|
75
80
|
export { createConsoleLogger } from './logger.js';
|
|
81
|
+
// The client-set User-Agent of the request in progress, for attribution
|
|
82
|
+
// only (e.g. marking a log line); never an auth, trust or routing input.
|
|
83
|
+
export { currentRequestUserAgent } from './request-context.js';
|
|
76
84
|
export { ChannelSessionNotFoundError, createGguiSessionChannelServer, DEFAULT_RENDER_CHANNEL_PATH, } from './ggui-session-channel.js';
|
|
77
85
|
export { resolveStorageFromConfig } from './storage.js';
|
|
78
86
|
export { DEFAULT_PAIRING_ADMIN_INIT_PATH, DEFAULT_PAIRING_PATH, mountPairingTransport, } from './pairing-transport.js';
|
|
@@ -107,6 +115,7 @@ export { MCP_INSTRUCTIONS_PRESETS, resolveMcpInstructions, } from './instruction
|
|
|
107
115
|
export { googleLoginProvider } from './oauth-providers/google.js';
|
|
108
116
|
export { githubLoginProvider } from './oauth-providers/github.js';
|
|
109
117
|
export { createOAuthProvidersStore } from './oauth-providers-store.js';
|
|
118
|
+
export { InMemoryOAuthStorage } from './oauth.js';
|
|
110
119
|
export { DEFAULT_ADMIN_OAUTH_PROVIDERS_PATH, mountAdminOAuthProvidersTransport, } from './admin-oauth-providers-transport.js';
|
|
111
120
|
export { DEFAULT_BUILDER_OWNER_ID, DEFAULT_THREADS_PATH, defaultThreadOwnerFromIdentity, mountThreadTransport, } from './thread-transport.js';
|
|
112
121
|
// Zero-config in-memory reference for the console shortCode → render
|
|
@@ -42,18 +42,16 @@ import type { LLMCaller } from "@ggui-ai/negotiator";
|
|
|
42
42
|
*
|
|
43
43
|
* `callStructured` (and `callStructuredMetered`, the same call with the
|
|
44
44
|
* response's token usage beside the tool input — ggui#1418) is wired for
|
|
45
|
-
* Anthropic only
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* onto `ProviderAdapter` as an optional method and wire each
|
|
56
|
-
* adapter; this in-place implementation stays the bridge until then.
|
|
45
|
+
* Anthropic only, through the shared structured call
|
|
46
|
+
* (`anthropicToolCall` in `@ggui-ai/ui-gen/providers`, ggui#1271): one
|
|
47
|
+
* `/v1/messages` request asking for one tool call, a forced
|
|
48
|
+
* `tool_choice` where the model accepts one, and every way the turn ends
|
|
49
|
+
* without the tool input thrown as a NAMED `AnthropicStructuredCallError`
|
|
50
|
+
* (re-exported from this package's index). The rerank judge and the synthesizer collapse that
|
|
51
|
+
* throw to their null-decision fallback, with the kind in the reason.
|
|
52
|
+
* Other providers (OpenAI, Google, OpenRouter, Bedrock) omit
|
|
53
|
+
* `callStructured`; consumers detect absence and fall back to
|
|
54
|
+
* regex-JSON extraction on the text path.
|
|
57
55
|
*
|
|
58
56
|
* Used by:
|
|
59
57
|
* - `@ggui-ai/negotiator/llm-rerank` (Tier 2 RAG match judge)
|
|
@@ -76,42 +74,6 @@ export interface BuildLlmCallerOptions {
|
|
|
76
74
|
readonly signal?: AbortSignal;
|
|
77
75
|
}
|
|
78
76
|
export declare function buildLlmCaller(selection: LlmSelection, providerKey: ProviderKeyRef, options?: BuildLlmCallerOptions): LLMCaller;
|
|
79
|
-
/**
|
|
80
|
-
* Thinking budget added to the caller's ANSWER budget when the model
|
|
81
|
-
* refuses a forced tool. Those are the always-thinking models: their
|
|
82
|
-
* thinking counts against `max_tokens` and comes before the tool call,
|
|
83
|
-
* so a caller's small answer budget (the rerank judge asks for 512)
|
|
84
|
-
* would be spent before the `tool_use` block exists. `max_tokens` is a
|
|
85
|
-
* ceiling, not spend.
|
|
86
|
-
*/
|
|
87
|
-
export declare const ALWAYS_THINKING_HEADROOM_TOKENS = 16000;
|
|
88
|
-
/** How a structured call ended without the tool input it asked for. */
|
|
89
|
-
export type AnthropicStructuredCallFailureKind =
|
|
90
|
-
/** The budget ran out (`stop_reason: max_tokens`) before the tool call. */
|
|
91
|
-
"max_tokens"
|
|
92
|
-
/** The model finished without calling the tool (possible under `auto`). */
|
|
93
|
-
| "no_tool_call"
|
|
94
|
-
/** The model declined (`stop_reason: refusal`). */
|
|
95
|
-
| "refusal"
|
|
96
|
-
/** The API answered non-2xx. */
|
|
97
|
-
| "http"
|
|
98
|
-
/** The body was not a Messages response. */
|
|
99
|
-
| "malformed";
|
|
100
|
-
/**
|
|
101
|
-
* A structured call that returned no tool input, NAMED by why. The kind
|
|
102
|
-
* is in the message too (`[max_tokens]` …), so a consumer that only
|
|
103
|
-
* surfaces the message — the rerank judge's `reason` — still reports
|
|
104
|
-
* which failure it was instead of an anonymous null decision.
|
|
105
|
-
*/
|
|
106
|
-
export declare class AnthropicStructuredCallError extends Error {
|
|
107
|
-
readonly kind: AnthropicStructuredCallFailureKind;
|
|
108
|
-
readonly status: number | undefined;
|
|
109
|
-
readonly stopReason: string | undefined;
|
|
110
|
-
constructor(kind: AnthropicStructuredCallFailureKind, detail: string, extra?: {
|
|
111
|
-
readonly status?: number;
|
|
112
|
-
readonly stopReason?: string;
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
77
|
/**
|
|
116
78
|
* Dependencies for `createLlmBackedHandshakeNegotiator`. Only
|
|
117
79
|
* `resolveLlm` is required; the rest carry default fallbacks.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-backed-negotiator.d.ts","sourceRoot":"","sources":["../src/llm-backed-negotiator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"llm-backed-negotiator.d.ts","sourceRoot":"","sources":["../src/llm-backed-negotiator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,qBAAqB,CAAC;AAG9D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,WAAW,EAAE,cAAc,EAC3B,OAAO,GAAE,qBAA0B,GAClC,SAAS,CAsDX;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAC/C;;;;;;OAMG;IACH,UAAU,EAAE,CACV,GAAG,EAAE,cAAc,KAEjB;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,WAAW,EAAE,cAAc,CAAA;KAAE,GACxD,OAAO,CAAC;QAAE,SAAS,EAAE,YAAY,CAAC;QAAC,WAAW,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC,GACxE,IAAI,CAAC;IACT;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;QACtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;QAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;KAChC,CAAC;IACF;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;IAClD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,CAAC,gCAAgC,EAAE,OAAO,GAAG,qBAAqB,GAAG,WAAW,CAAC,GAC1F,aAAa,EAAE,CAQjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,gCAAgC,GACrC,mBAAmB,CAkCrB"}
|
|
@@ -31,8 +31,7 @@
|
|
|
31
31
|
* `resolveLlm` is wired into `generation`.
|
|
32
32
|
*/
|
|
33
33
|
import { decideHandshake, } from "@ggui-ai/mcp-server-handlers/renders";
|
|
34
|
-
import {
|
|
35
|
-
import { selectAdapter } from "@ggui-ai/ui-gen/providers";
|
|
34
|
+
import { anthropicToolCall, selectAdapter } from "@ggui-ai/ui-gen/providers";
|
|
36
35
|
export function buildLlmCaller(selection, providerKey, options = {}) {
|
|
37
36
|
const adapter = selectAdapter(selection.provider);
|
|
38
37
|
const isAnthropic = selection.provider === "anthropic";
|
|
@@ -65,149 +64,20 @@ export function buildLlmCaller(selection, providerKey, options = {}) {
|
|
|
65
64
|
},
|
|
66
65
|
};
|
|
67
66
|
if (isAnthropic) {
|
|
68
|
-
const metered = (systemPrompt, userMessage, tool, maxTokens) =>
|
|
67
|
+
const metered = (systemPrompt, userMessage, tool, maxTokens) => anthropicToolCall({
|
|
69
68
|
apiKey: providerKey.key,
|
|
70
69
|
model: selection.model,
|
|
71
70
|
systemPrompt,
|
|
72
|
-
userMessage,
|
|
71
|
+
userPrompt: userMessage,
|
|
73
72
|
tool,
|
|
74
|
-
maxTokens,
|
|
73
|
+
...(maxTokens !== undefined ? { maxTokens } : {}),
|
|
75
74
|
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
76
|
-
});
|
|
75
|
+
}).then(({ input, usage }) => ({ value: input, ...(usage !== undefined ? { usage } : {}) }));
|
|
77
76
|
caller.callStructuredMetered = metered;
|
|
78
77
|
caller.callStructured = async (systemPrompt, userMessage, tool, maxTokens) => (await metered(systemPrompt, userMessage, tool, maxTokens)).value;
|
|
79
78
|
}
|
|
80
79
|
return caller;
|
|
81
80
|
}
|
|
82
|
-
/**
|
|
83
|
-
* Thinking budget added to the caller's ANSWER budget when the model
|
|
84
|
-
* refuses a forced tool. Those are the always-thinking models: their
|
|
85
|
-
* thinking counts against `max_tokens` and comes before the tool call,
|
|
86
|
-
* so a caller's small answer budget (the rerank judge asks for 512)
|
|
87
|
-
* would be spent before the `tool_use` block exists. `max_tokens` is a
|
|
88
|
-
* ceiling, not spend.
|
|
89
|
-
*/
|
|
90
|
-
export const ALWAYS_THINKING_HEADROOM_TOKENS = 16_000;
|
|
91
|
-
/**
|
|
92
|
-
* A structured call that returned no tool input, NAMED by why. The kind
|
|
93
|
-
* is in the message too (`[max_tokens]` …), so a consumer that only
|
|
94
|
-
* surfaces the message — the rerank judge's `reason` — still reports
|
|
95
|
-
* which failure it was instead of an anonymous null decision.
|
|
96
|
-
*/
|
|
97
|
-
export class AnthropicStructuredCallError extends Error {
|
|
98
|
-
kind;
|
|
99
|
-
status;
|
|
100
|
-
stopReason;
|
|
101
|
-
constructor(kind, detail, extra = {}) {
|
|
102
|
-
super(`anthropic structured call [${kind}]: ${detail}`);
|
|
103
|
-
this.name = "AnthropicStructuredCallError";
|
|
104
|
-
this.kind = kind;
|
|
105
|
-
this.status = extra.status;
|
|
106
|
-
this.stopReason = extra.stopReason;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Anthropic-direct tool-use call; returns the tool's `input` JSON.
|
|
111
|
-
*
|
|
112
|
-
* Two request shapes, chosen by the shared model-rule predicate
|
|
113
|
-
* (`anthropicRejectsForcedToolChoice`, the same list the harness router
|
|
114
|
-
* reads — one list, so a model the API starts refusing is added once):
|
|
115
|
-
*
|
|
116
|
-
* - Models that accept a forced tool: `tool_choice: {type: 'tool'}`
|
|
117
|
-
* and the caller's `max_tokens`, as before.
|
|
118
|
-
* - Models that refuse it (the always-thinking family): a forced tool
|
|
119
|
-
* is an HTTP 400 on every call, so they get `tool_choice: auto` with
|
|
120
|
-
* at most one call, an instruction naming the tool appended to the
|
|
121
|
-
* system prompt, and `ALWAYS_THINKING_HEADROOM_TOKENS` added to the
|
|
122
|
-
* caller's budget. `strict: true` is deliberately NOT sent: the two
|
|
123
|
-
* consumers' schemas carry keywords strict tool use rejects (the
|
|
124
|
-
* rerank judge's `minimum`/`maximum`, the synthesizer's map-shaped
|
|
125
|
-
* `additionalProperties`), so it would trade one 400 for another;
|
|
126
|
-
* both consumers already validate the input they get back.
|
|
127
|
-
*
|
|
128
|
-
* Every way the turn ends without the tool input throws an
|
|
129
|
-
* `AnthropicStructuredCallError` whose kind says which — the caller
|
|
130
|
-
* (rerank judge, synthesizer) collapses it to its null-decision
|
|
131
|
-
* fallback, and the kind rides along in the reason.
|
|
132
|
-
*/
|
|
133
|
-
async function anthropicCallStructured(args) {
|
|
134
|
-
const answerBudget = args.maxTokens ?? 1024;
|
|
135
|
-
const refusesForcedTool = anthropicRejectsForcedToolChoice(args.model);
|
|
136
|
-
const body = {
|
|
137
|
-
model: args.model,
|
|
138
|
-
max_tokens: refusesForcedTool ? answerBudget + ALWAYS_THINKING_HEADROOM_TOKENS : answerBudget,
|
|
139
|
-
// `temperature` was pinned to 0 for deterministic structured
|
|
140
|
-
// output, but Anthropic deprecated the parameter on newer
|
|
141
|
-
// tool-use models (Haiku 4.5+ rejects it with HTTP 400). Dropped.
|
|
142
|
-
// Residual stochasticity is in field VALUES (e.g. action names);
|
|
143
|
-
// both consumers (synthesizer + rerank judge) MUST tolerate
|
|
144
|
-
// paraphrase via canonical-key normalisation rather than relying
|
|
145
|
-
// on temperature=0.
|
|
146
|
-
system: refusesForcedTool
|
|
147
|
-
? `${args.systemPrompt}\n\nAnswer by calling the \`${args.tool.name}\` tool exactly once. Do not answer in text.`
|
|
148
|
-
: args.systemPrompt,
|
|
149
|
-
messages: [{ role: "user", content: args.userMessage }],
|
|
150
|
-
tools: [
|
|
151
|
-
{
|
|
152
|
-
name: args.tool.name,
|
|
153
|
-
description: args.tool.description,
|
|
154
|
-
input_schema: args.tool.input_schema,
|
|
155
|
-
},
|
|
156
|
-
],
|
|
157
|
-
// Forced tool use where the model allows it — the model MUST emit
|
|
158
|
-
// exactly this tool. Where it doesn't, `auto` + one call + the
|
|
159
|
-
// instruction above, and a missing call is a named failure below.
|
|
160
|
-
tool_choice: refusesForcedTool
|
|
161
|
-
? { type: "auto", disable_parallel_tool_use: true }
|
|
162
|
-
: { type: "tool", name: args.tool.name },
|
|
163
|
-
};
|
|
164
|
-
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
165
|
-
method: "POST",
|
|
166
|
-
headers: {
|
|
167
|
-
"x-api-key": args.apiKey,
|
|
168
|
-
"anthropic-version": "2023-06-01",
|
|
169
|
-
"content-type": "application/json",
|
|
170
|
-
},
|
|
171
|
-
body: JSON.stringify(body),
|
|
172
|
-
...(args.signal !== undefined ? { signal: args.signal } : {}),
|
|
173
|
-
});
|
|
174
|
-
if (!response.ok) {
|
|
175
|
-
const text = await response.text().catch(() => "");
|
|
176
|
-
throw new AnthropicStructuredCallError("http", `HTTP ${response.status}: ${text.slice(0, 500)}`, {
|
|
177
|
-
status: response.status,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
const json = await response.json();
|
|
181
|
-
if (!isRecord(json) || !Array.isArray(json["content"])) {
|
|
182
|
-
throw new AnthropicStructuredCallError("malformed", "response body is not a Messages response");
|
|
183
|
-
}
|
|
184
|
-
const stopReason = typeof json["stop_reason"] === "string" ? json["stop_reason"] : undefined;
|
|
185
|
-
const toolUse = json["content"].find((block) => isRecord(block) && block["type"] === "tool_use" && block["name"] === args.tool.name);
|
|
186
|
-
if (toolUse !== undefined && toolUse["input"] !== undefined) {
|
|
187
|
-
const usage = readMessagesUsage(json["usage"]);
|
|
188
|
-
return { value: toolUse["input"], ...(usage !== undefined ? { usage } : {}) };
|
|
189
|
-
}
|
|
190
|
-
if (stopReason === "max_tokens") {
|
|
191
|
-
throw new AnthropicStructuredCallError("max_tokens", `stop_reason=max_tokens before the "${args.tool.name}" tool_use block (max_tokens=${body.max_tokens})`, { stopReason });
|
|
192
|
-
}
|
|
193
|
-
if (stopReason === "refusal") {
|
|
194
|
-
throw new AnthropicStructuredCallError("refusal", `the model declined (stop_reason=refusal)`, { stopReason });
|
|
195
|
-
}
|
|
196
|
-
throw new AnthropicStructuredCallError("no_tool_call", `the turn ended (stop_reason=${stopReason ?? "absent"}) without a "${args.tool.name}" tool_use block`, stopReason !== undefined ? { stopReason } : {});
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* The token usage of a Messages response, as `{ input, output }`: its
|
|
200
|
-
* `usage.input_tokens` and `usage.output_tokens` when both are numbers,
|
|
201
|
-
* else absent (unmetered, never zeros — ggui#1418). No `cache_control` is
|
|
202
|
-
* sent on this call, so the cache token counts are not added.
|
|
203
|
-
*/
|
|
204
|
-
function readMessagesUsage(usage) {
|
|
205
|
-
if (!isRecord(usage))
|
|
206
|
-
return undefined;
|
|
207
|
-
const input = usage["input_tokens"];
|
|
208
|
-
const output = usage["output_tokens"];
|
|
209
|
-
return typeof input === "number" && typeof output === "number" ? { input, output } : undefined;
|
|
210
|
-
}
|
|
211
81
|
/**
|
|
212
82
|
* Build the handshake pool list: the per-app pool (from `cache`) first —
|
|
213
83
|
* so a deployment's own blueprints win on exact-key first-match — then
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-apps-outbound.d.ts","sourceRoot":"","sources":["../src/mcp-apps-outbound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAWL,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAmBjF,OAAO,EAgBL,KAAK,sBAAsB,EAE5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAG3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-apps-outbound.d.ts","sourceRoot":"","sources":["../src/mcp-apps-outbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -325,7 +325,10 @@ function readMetaFromCallToolResult(params){
|
|
|
325
325
|
return meta;
|
|
326
326
|
}
|
|
327
327
|
window.addEventListener('message',function(ev){
|
|
328
|
-
|
|
328
|
+
// Only the embedding window speaks for the host: a reply or a
|
|
329
|
+
// tool-result from any other frame is dropped, unanswered.
|
|
330
|
+
if(!ev||ev.source!==window.parent)return;
|
|
331
|
+
var m=ev.data;
|
|
329
332
|
if(!m||m.jsonrpc!=='2.0')return;
|
|
330
333
|
if(m.id!=null&&pending[m.id]){
|
|
331
334
|
var p=pending[m.id];delete pending[m.id];
|
|
@@ -556,7 +559,9 @@ const GGUI_INLINE_SHELL_BUFFER_SCRIPT_BODY = `
|
|
|
556
559
|
(function(){'use strict';
|
|
557
560
|
var buf=window.__GGUI_PENDING_TOOL_RESULTS__=window.__GGUI_PENDING_TOOL_RESULTS__||[];
|
|
558
561
|
window.addEventListener('message',function(ev){
|
|
559
|
-
|
|
562
|
+
// Only the embedding window's tool-results are buffered.
|
|
563
|
+
if(!ev||ev.source!==window.parent)return;
|
|
564
|
+
var m=ev.data;
|
|
560
565
|
if(!m||m.jsonrpc!=='2.0'||m.method!=='ui/notifications/tool-result')return;
|
|
561
566
|
buf.push(m.params);
|
|
562
567
|
if(buf.length>8)buf.splice(0,buf.length-8);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-endpoint-routes.d.ts","sourceRoot":"","sources":["../src/mcp-endpoint-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElF,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAEvC,OAAO,
|
|
1
|
+
{"version":3,"file":"mcp-endpoint-routes.d.ts","sourceRoot":"","sources":["../src/mcp-endpoint-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ import { GGUI_HOST_CAPABILITIES_HEADER, MCP_ERROR_CODES, isRecord, parseHostCapa
|
|
|
35
35
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
36
36
|
import { randomUUID } from "node:crypto";
|
|
37
37
|
import { resolveIdentity, UnauthenticatedError } from "./auth.js";
|
|
38
|
-
import { buildMcpServer } from "./build-mcp.js";
|
|
38
|
+
import { buildMcpServer, observeToolCallRefusals } from "./build-mcp.js";
|
|
39
39
|
import { CONTROL_PATH, DATA_PLANE_AUDIENCES, filterHandlersByAudience, } from "./control-service.js";
|
|
40
40
|
import { buildWwwAuthenticate, resolveIssuerUrl } from "./oauth.js";
|
|
41
41
|
/** The JSON-RPC error object a mapped result becomes on the wire. */
|
|
@@ -382,7 +382,10 @@ export function mountMcpEndpoints(opts) {
|
|
|
382
382
|
mcp.close().catch(() => undefined);
|
|
383
383
|
});
|
|
384
384
|
try {
|
|
385
|
-
|
|
385
|
+
// ggui#1995 — the server connects through the refusal observer, so a
|
|
386
|
+
// `tools/call` the SDK refuses before any handler (element ceiling,
|
|
387
|
+
// input schema, unknown tool) still logs its `tool_invoked` line.
|
|
388
|
+
await mcp.connect(observeToolCallRefusals(transport, mcp, reqLogger, () => als.getStore() ?? ctx));
|
|
386
389
|
await als.run(ctx, () => transport.handleRequest(req, res, req.body));
|
|
387
390
|
}
|
|
388
391
|
catch (err) {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import type { AuthAdapter, PairingService } from "@ggui-ai/mcp-server-core";
|
|
20
20
|
import type { Express } from "express";
|
|
21
21
|
import { type OAuthConfig, type OAuthStorage } from "./oauth.js";
|
|
22
|
+
import type { Logger } from "./logger.js";
|
|
22
23
|
interface MountOptions {
|
|
23
24
|
/** Express app to mount onto. */
|
|
24
25
|
readonly app: Express;
|
|
@@ -58,6 +59,8 @@ interface MountOptions {
|
|
|
58
59
|
* `listen()`, which is strictly after composition completes.
|
|
59
60
|
*/
|
|
60
61
|
readonly getPairingService: () => PairingService | null;
|
|
62
|
+
/** Where a failed OAuth route logs its error (the response never carries it). */
|
|
63
|
+
readonly logger: Logger;
|
|
61
64
|
}
|
|
62
65
|
/**
|
|
63
66
|
* Mount the OAuth discovery + auth + token endpoints onto the express
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-as-routes.d.ts","sourceRoot":"","sources":["../src/oauth-as-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"oauth-as-routes.d.ts","sourceRoot":"","sources":["../src/oauth-as-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAE1D,OAAO,EAQL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,UAAU,YAAY;IACpB,iCAAiC;IACjC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACxD,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CA+I5E"}
|
package/dist/oauth-as-routes.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* clients (Claude Desktop, claude.ai, Goose, etc.) bail with
|
|
17
17
|
* "couldn't reach".
|
|
18
18
|
*/
|
|
19
|
-
import { handleAuthorizationServerMetadata, handleAuthorizeGet, handleAuthorizePost, handleProtectedResourceMetadata, handleRegister, handleToken, } from "./oauth.js";
|
|
19
|
+
import { handleAuthorizationServerMetadata, handleAuthorizeGet, handleAuthorizePost, handleProtectedResourceMetadata, handleRegister, handleToken, renderErrorPage, } from "./oauth.js";
|
|
20
20
|
/**
|
|
21
21
|
* Mount the OAuth discovery + auth + token endpoints onto the express
|
|
22
22
|
* app. Also flips `trust proxy` on — nginx-ingress + ALB both
|
|
@@ -111,16 +111,23 @@ export function mountOAuthAuthorizationServerRoutes(opts) {
|
|
|
111
111
|
app.get(`/.well-known/oauth-authorization-server${universalMcpPath}`, (req, res) => handleAuthorizationServerMetadata(req, res, oauthConfig));
|
|
112
112
|
}
|
|
113
113
|
app.get("/.well-known/oauth-authorization-server", (req, res) => handleAuthorizationServerMetadata(req, res, oauthConfig));
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
114
|
+
// A handler that throws (a storage that fails) answers a defined error,
|
|
115
|
+
// never a hung request, and never the error itself: the browser routes get
|
|
116
|
+
// the generic error page, the JSON routes RFC 6749 / 7591's `server_error`,
|
|
117
|
+
// and the error goes to the server log.
|
|
118
|
+
const failClosed = (route, shape, handler) => (req, res) => {
|
|
119
|
+
handler(req, res).catch((err) => {
|
|
120
|
+
opts.logger.error("oauth_route_failed", { route, error: err instanceof Error ? err.message : String(err) });
|
|
121
|
+
if (res.headersSent)
|
|
122
|
+
return;
|
|
123
|
+
if (shape === "html")
|
|
124
|
+
res.status(500).type("html").send(renderErrorPage("Something went wrong on the server. Please try again."));
|
|
125
|
+
else
|
|
126
|
+
res.status(500).json({ error: "server_error", error_description: "The authorization server could not complete the request." });
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
app.post("/oauth/register", failClosed("register", "json", (req, res) => handleRegister(req, res, oauthConfig, oauthStorage)));
|
|
130
|
+
app.get("/oauth/authorize", failClosed("authorize", "html", (req, res) => handleAuthorizeGet(req, res, oauthConfig, oauthStorage)));
|
|
131
|
+
app.post("/oauth/authorize", failClosed("authorize", "html", (req, res) => handleAuthorizePost(req, res, oauthConfig, oauthStorage, auth, getPairingService())));
|
|
132
|
+
app.post("/oauth/token", failClosed("token", "json", (req, res) => handleToken(req, res, oauthStorage)));
|
|
126
133
|
}
|
package/dist/oauth.d.ts
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* server validates PKCE, returns the user's `ggui_user_*` key as
|
|
29
29
|
* the `access_token`.
|
|
30
30
|
* 8. Client retries `/mcp` with `Authorization: Bearer ggui_user_*`
|
|
31
|
-
* →
|
|
31
|
+
* → the configured {@link AuthAdapter} accepts it, as it would
|
|
32
|
+
* any bearer it issued. ✅
|
|
32
33
|
*
|
|
33
34
|
* ## Why the access token IS the API key
|
|
34
35
|
*
|
|
@@ -48,13 +49,14 @@
|
|
|
48
49
|
*
|
|
49
50
|
* ## Storage
|
|
50
51
|
*
|
|
51
|
-
* Auth codes + DCR clients live in-memory ({@link InMemoryOAuthStorage})
|
|
52
|
-
*
|
|
53
|
-
* balancer),
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
52
|
+
* Auth codes + DCR clients live in-memory ({@link InMemoryOAuthStorage}),
|
|
53
|
+
* which is correct for a single replica. With more than one replica
|
|
54
|
+
* (2+ processes behind one load balancer), one sign-in's requests can
|
|
55
|
+
* reach different replicas: the client registers and exchanges the code,
|
|
56
|
+
* while the user's browser approves at `/oauth/authorize`. Sticky
|
|
57
|
+
* sessions do not help, because those are two different clients. Pass a
|
|
58
|
+
* shared {@link OAuthStorage} (one every replica reads) through the
|
|
59
|
+
* `oauth.storage` config option.
|
|
58
60
|
*
|
|
59
61
|
* DCR clients are short-lived in practice — Claude Desktop registers
|
|
60
62
|
* once per install + caches the `client_id`. A server restart drops all
|
|
@@ -73,9 +75,13 @@ export interface OAuthConfig {
|
|
|
73
75
|
readonly issuerUrl?: string;
|
|
74
76
|
/**
|
|
75
77
|
* Storage seam for auth codes + DCR clients. Defaults to
|
|
76
|
-
* {@link InMemoryOAuthStorage}
|
|
77
|
-
*
|
|
78
|
-
*
|
|
78
|
+
* {@link InMemoryOAuthStorage}, which holds them in this server
|
|
79
|
+
* process: correct for a single replica. With more than one replica,
|
|
80
|
+
* one sign-in's requests can land on different replicas (the client
|
|
81
|
+
* registers and exchanges the code, the user's browser approves), so a
|
|
82
|
+
* multi-replica deployment must provide a shared implementation of
|
|
83
|
+
* {@link OAuthStorage}. Session affinity does not help: the browser and
|
|
84
|
+
* the client are different clients.
|
|
79
85
|
*/
|
|
80
86
|
readonly storage?: OAuthStorage;
|
|
81
87
|
/**
|
|
@@ -87,7 +93,7 @@ export interface OAuthConfig {
|
|
|
87
93
|
* user's chosen `api_key`.
|
|
88
94
|
*
|
|
89
95
|
* Trade-off: the consent UI sees every OAuth param + the user's
|
|
90
|
-
*
|
|
96
|
+
* signed-in session — it MUST be operator-controlled (same trust
|
|
91
97
|
* boundary as the MCP server itself). Cross-origin POST is fine
|
|
92
98
|
* (form-encoded → no CORS preflight); the response is a 302 to the
|
|
93
99
|
* client's `redirect_uri` which the browser follows transparently.
|
|
@@ -150,8 +156,7 @@ export interface AuthCodeRecord {
|
|
|
150
156
|
* issued by /token are opaque static keys (`ggui_user_*`); the
|
|
151
157
|
* appId-from-resource binding is enforced at the auth-code →
|
|
152
158
|
* token boundary, not via JWT claims. Runtime appId resolution
|
|
153
|
-
* keeps reading the key
|
|
154
|
-
* `GguiUserApiKey` row).
|
|
159
|
+
* keeps reading it from the key itself.
|
|
155
160
|
*/
|
|
156
161
|
readonly resource?: string;
|
|
157
162
|
}
|
|
@@ -164,7 +169,7 @@ export interface ClientRecord {
|
|
|
164
169
|
readonly createdAt: number;
|
|
165
170
|
/**
|
|
166
171
|
* RFC 8707 resource indicator from this client's most recent
|
|
167
|
-
* `/oauth/authorize` request
|
|
172
|
+
* `/oauth/authorize` request. Captured
|
|
168
173
|
* each time `handleAuthorizePost` consumes the params — surfaces
|
|
169
174
|
* "Connected to: <App>" on the operator's Connected Apps console
|
|
170
175
|
* once that surface goes live. DCR itself doesn't carry resource
|
|
@@ -316,9 +321,8 @@ export declare function handleAuthorizeGet(req: Request, res: Response, config:
|
|
|
316
321
|
* Validation flow:
|
|
317
322
|
* 1. Re-validate the OAuth params (defense — caller could skip /GET).
|
|
318
323
|
* 2. Resolve the pasted key through `auth.authenticate()` — accepts
|
|
319
|
-
* any key the adapter accepts.
|
|
320
|
-
*
|
|
321
|
-
* `lookupUser` binding.
|
|
324
|
+
* any key the configured adapter accepts, e.g. a `ggui_user_*` key
|
|
325
|
+
* it issued.
|
|
322
326
|
* 3. On success: write {code, accessToken=key, codeChallenge,
|
|
323
327
|
* redirectUri, clientId} to storage. 5-minute TTL.
|
|
324
328
|
* 4. Redirect to `redirect_uri?code=<code>&state=<state>&iss=<issuer>`
|
|
@@ -347,5 +351,7 @@ export declare function handleAuthorizePost(req: Request, res: Response, config:
|
|
|
347
351
|
* 400 status code.
|
|
348
352
|
*/
|
|
349
353
|
export declare function handleToken(req: Request, res: Response, storage: OAuthStorage): Promise<void>;
|
|
354
|
+
/** The OAuth routes' HTML error page (also used by the routes' failure handler). */
|
|
355
|
+
export declare function renderErrorPage(message: string): string;
|
|
350
356
|
export {};
|
|
351
357
|
//# sourceMappingURL=oauth.d.ts.map
|
package/dist/oauth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|