@superblocksteam/gateway 2.0.0-SNAPSHOT.1d4c72c0ab174c21
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/LICENSE.txt +87 -0
- package/README.md +291 -0
- package/dist/agents/resolve-orchestrator-url.d.ts +22 -0
- package/dist/agents/resolve-orchestrator-url.js +38 -0
- package/dist/agents/resolve-orchestrator-url.js.map +1 -0
- package/dist/capabilities/integration-metadata.d.ts +28 -0
- package/dist/capabilities/integration-metadata.js +174 -0
- package/dist/capabilities/integration-metadata.js.map +1 -0
- package/dist/capabilities/lifecycle.d.ts +93 -0
- package/dist/capabilities/lifecycle.js +3450 -0
- package/dist/capabilities/lifecycle.js.map +1 -0
- package/dist/capabilities/query-integration.d.ts +14 -0
- package/dist/capabilities/query-integration.js +172 -0
- package/dist/capabilities/query-integration.js.map +1 -0
- package/dist/capabilities/source-files-archive.d.ts +11 -0
- package/dist/capabilities/source-files-archive.js +54 -0
- package/dist/capabilities/source-files-archive.js.map +1 -0
- package/dist/capabilities/types.d.ts +542 -0
- package/dist/capabilities/types.js +86 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/capture/browser-contract.d.ts +46 -0
- package/dist/capture/browser-contract.js +34 -0
- package/dist/capture/browser-contract.js.map +1 -0
- package/dist/capture/browser-instructions.d.ts +10 -0
- package/dist/capture/browser-instructions.js +18 -0
- package/dist/capture/browser-instructions.js.map +1 -0
- package/dist/capture/capture-library-probe.d.ts +55 -0
- package/dist/capture/capture-library-probe.js +177 -0
- package/dist/capture/capture-library-probe.js.map +1 -0
- package/dist/capture/capture-library.d.ts +52 -0
- package/dist/capture/capture-library.js +249 -0
- package/dist/capture/capture-library.js.map +1 -0
- package/dist/capture/classify-library-paint.d.ts +21 -0
- package/dist/capture/classify-library-paint.js +13 -0
- package/dist/capture/classify-library-paint.js.map +1 -0
- package/dist/capture/host-mcp-scan.d.ts +16 -0
- package/dist/capture/host-mcp-scan.js +64 -0
- package/dist/capture/host-mcp-scan.js.map +1 -0
- package/dist/capture/library-parent-script.d.ts +35 -0
- package/dist/capture/library-parent-script.js +82 -0
- package/dist/capture/library-parent-script.js.map +1 -0
- package/dist/capture/mode.d.ts +29 -0
- package/dist/capture/mode.js +65 -0
- package/dist/capture/mode.js.map +1 -0
- package/dist/config.d.ts +148 -0
- package/dist/config.js +111 -0
- package/dist/config.js.map +1 -0
- package/dist/debug.d.ts +2 -0
- package/dist/debug.js +9 -0
- package/dist/debug.js.map +1 -0
- package/dist/deps.d.ts +38 -0
- package/dist/deps.js +2 -0
- package/dist/deps.js.map +1 -0
- package/dist/health/readiness.d.ts +99 -0
- package/dist/health/readiness.js +202 -0
- package/dist/health/readiness.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/filters.d.ts +8 -0
- package/dist/integrations/filters.js +40 -0
- package/dist/integrations/filters.js.map +1 -0
- package/dist/integrations/map.d.ts +27 -0
- package/dist/integrations/map.js +43 -0
- package/dist/integrations/map.js.map +1 -0
- package/dist/integrations/profile-key.d.ts +19 -0
- package/dist/integrations/profile-key.js +35 -0
- package/dist/integrations/profile-key.js.map +1 -0
- package/dist/integrations/read-only-postgres-query.d.ts +2 -0
- package/dist/integrations/read-only-postgres-query.js +164 -0
- package/dist/integrations/read-only-postgres-query.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +5 -0
- package/dist/main.js.map +1 -0
- package/dist/orchestrator/client.d.ts +62 -0
- package/dist/orchestrator/client.js +160 -0
- package/dist/orchestrator/client.js.map +1 -0
- package/dist/playwright/ensure-chromium.d.ts +24 -0
- package/dist/playwright/ensure-chromium.js +60 -0
- package/dist/playwright/ensure-chromium.js.map +1 -0
- package/dist/preview/capture-screenshot.d.ts +67 -0
- package/dist/preview/capture-screenshot.js +179 -0
- package/dist/preview/capture-screenshot.js.map +1 -0
- package/dist/preview/viewer-url.d.ts +82 -0
- package/dist/preview/viewer-url.js +130 -0
- package/dist/preview/viewer-url.js.map +1 -0
- package/dist/process/fault-barrier.d.ts +55 -0
- package/dist/process/fault-barrier.js +113 -0
- package/dist/process/fault-barrier.js.map +1 -0
- package/dist/sabs/agent-facing-text.d.ts +35 -0
- package/dist/sabs/agent-facing-text.js +165 -0
- package/dist/sabs/agent-facing-text.js.map +1 -0
- package/dist/sabs/app-state.d.ts +126 -0
- package/dist/sabs/app-state.js +332 -0
- package/dist/sabs/app-state.js.map +1 -0
- package/dist/sabs/awaited-decision.d.ts +47 -0
- package/dist/sabs/awaited-decision.js +124 -0
- package/dist/sabs/awaited-decision.js.map +1 -0
- package/dist/sabs/browser-context.d.ts +53 -0
- package/dist/sabs/browser-context.js +92 -0
- package/dist/sabs/browser-context.js.map +1 -0
- package/dist/sabs/editor-client-methods.d.ts +164 -0
- package/dist/sabs/editor-client-methods.js +750 -0
- package/dist/sabs/editor-client-methods.js.map +1 -0
- package/dist/sabs/editor-socket.d.ts +84 -0
- package/dist/sabs/editor-socket.js +64 -0
- package/dist/sabs/editor-socket.js.map +1 -0
- package/dist/sabs/recent-tool-runs.d.ts +14 -0
- package/dist/sabs/recent-tool-runs.js +61 -0
- package/dist/sabs/recent-tool-runs.js.map +1 -0
- package/dist/sabs/session-peer.d.ts +392 -0
- package/dist/sabs/session-peer.js +11 -0
- package/dist/sabs/session-peer.js.map +1 -0
- package/dist/sabs/streamed-reply.d.ts +42 -0
- package/dist/sabs/streamed-reply.js +110 -0
- package/dist/sabs/streamed-reply.js.map +1 -0
- package/dist/sabs/turn-collector.d.ts +169 -0
- package/dist/sabs/turn-collector.js +506 -0
- package/dist/sabs/turn-collector.js.map +1 -0
- package/dist/sabs/websocket-session-peer.d.ts +540 -0
- package/dist/sabs/websocket-session-peer.js +3289 -0
- package/dist/sabs/websocket-session-peer.js.map +1 -0
- package/dist/security/constant-time.d.ts +9 -0
- package/dist/security/constant-time.js +13 -0
- package/dist/security/constant-time.js.map +1 -0
- package/dist/server/client.d.ts +405 -0
- package/dist/server/client.js +684 -0
- package/dist/server/client.js.map +1 -0
- package/dist/server/identity-reads.d.ts +76 -0
- package/dist/server/identity-reads.js +209 -0
- package/dist/server/identity-reads.js.map +1 -0
- package/dist/start.d.ts +24 -0
- package/dist/start.js +81 -0
- package/dist/start.js.map +1 -0
- package/dist/stores/memory.d.ts +42 -0
- package/dist/stores/memory.js +121 -0
- package/dist/stores/memory.js.map +1 -0
- package/dist/stores/types.d.ts +74 -0
- package/dist/stores/types.js +11 -0
- package/dist/stores/types.js.map +1 -0
- package/dist/telemetry/mcp-client.d.ts +22 -0
- package/dist/telemetry/mcp-client.js +140 -0
- package/dist/telemetry/mcp-client.js.map +1 -0
- package/dist/telemetry/metrics.d.ts +41 -0
- package/dist/telemetry/metrics.js +103 -0
- package/dist/telemetry/metrics.js.map +1 -0
- package/dist/telemetry/runtime.d.ts +9 -0
- package/dist/telemetry/runtime.js +118 -0
- package/dist/telemetry/runtime.js.map +1 -0
- package/dist/transports/mcp/admin-tools.d.ts +56 -0
- package/dist/transports/mcp/admin-tools.js +252 -0
- package/dist/transports/mcp/admin-tools.js.map +1 -0
- package/dist/transports/mcp/app-status-html.d.ts +11 -0
- package/dist/transports/mcp/app-status-html.js +899 -0
- package/dist/transports/mcp/app-status-html.js.map +1 -0
- package/dist/transports/mcp/client-presentation.d.ts +16 -0
- package/dist/transports/mcp/client-presentation.js +13 -0
- package/dist/transports/mcp/client-presentation.js.map +1 -0
- package/dist/transports/mcp/cowork-editor-url.d.ts +6 -0
- package/dist/transports/mcp/cowork-editor-url.js +10 -0
- package/dist/transports/mcp/cowork-editor-url.js.map +1 -0
- package/dist/transports/mcp/decision-card-html.d.ts +26 -0
- package/dist/transports/mcp/decision-card-html.js +876 -0
- package/dist/transports/mcp/decision-card-html.js.map +1 -0
- package/dist/transports/mcp/decision-elicitation.d.ts +116 -0
- package/dist/transports/mcp/decision-elicitation.js +292 -0
- package/dist/transports/mcp/decision-elicitation.js.map +1 -0
- package/dist/transports/mcp/dispatch-probe.d.ts +24 -0
- package/dist/transports/mcp/dispatch-probe.js +48 -0
- package/dist/transports/mcp/dispatch-probe.js.map +1 -0
- package/dist/transports/mcp/editor-document-probe.d.ts +4 -0
- package/dist/transports/mcp/editor-document-probe.js +35 -0
- package/dist/transports/mcp/editor-document-probe.js.map +1 -0
- package/dist/transports/mcp/editor-integration-setup-url.d.ts +8 -0
- package/dist/transports/mcp/editor-integration-setup-url.js +23 -0
- package/dist/transports/mcp/editor-integration-setup-url.js.map +1 -0
- package/dist/transports/mcp/format-tool-content.d.ts +20 -0
- package/dist/transports/mcp/format-tool-content.js +89 -0
- package/dist/transports/mcp/format-tool-content.js.map +1 -0
- package/dist/transports/mcp/instructions/index.d.ts +23 -0
- package/dist/transports/mcp/instructions/index.js +81 -0
- package/dist/transports/mcp/instructions/index.js.map +1 -0
- package/dist/transports/mcp/instructions/result.d.ts +18 -0
- package/dist/transports/mcp/instructions/result.js +58 -0
- package/dist/transports/mcp/instructions/result.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/ask-user.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/ask-user.js +17 -0
- package/dist/transports/mcp/instructions/tools/ask-user.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.js +75 -0
- package/dist/transports/mcp/instructions/tools/check-app-progress.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.js +23 -0
- package/dist/transports/mcp/instructions/tools/check-publish-progress.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/copy.d.ts +14 -0
- package/dist/transports/mcp/instructions/tools/copy.js +35 -0
- package/dist/transports/mcp/instructions/tools/copy.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/create-integration.d.ts +4 -0
- package/dist/transports/mcp/instructions/tools/create-integration.js +41 -0
- package/dist/transports/mcp/instructions/tools/create-integration.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/edit-app.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/edit-app.js +18 -0
- package/dist/transports/mcp/instructions/tools/edit-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/get-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/get-app.js +47 -0
- package/dist/transports/mcp/instructions/tools/get-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.js +13 -0
- package/dist/transports/mcp/instructions/tools/get-integration-metadata.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/index.d.ts +7 -0
- package/dist/transports/mcp/instructions/tools/index.js +26 -0
- package/dist/transports/mcp/instructions/tools/index.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/preview-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/preview-app.js +14 -0
- package/dist/transports/mcp/instructions/tools/preview-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/publish-app.d.ts +3 -0
- package/dist/transports/mcp/instructions/tools/publish-app.js +23 -0
- package/dist/transports/mcp/instructions/tools/publish-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/start-app.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/start-app.js +22 -0
- package/dist/transports/mcp/instructions/tools/start-app.js.map +1 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.d.ts +2 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.js +13 -0
- package/dist/transports/mcp/instructions/tools/upload-artifact.js.map +1 -0
- package/dist/transports/mcp/mcp-app-brand-css.d.ts +1 -0
- package/dist/transports/mcp/mcp-app-brand-css.js +180 -0
- package/dist/transports/mcp/mcp-app-brand-css.js.map +1 -0
- package/dist/transports/mcp/mount.d.ts +22 -0
- package/dist/transports/mcp/mount.js +1040 -0
- package/dist/transports/mcp/mount.js.map +1 -0
- package/dist/transports/mcp/native-browser-presence.d.ts +45 -0
- package/dist/transports/mcp/native-browser-presence.js +158 -0
- package/dist/transports/mcp/native-browser-presence.js.map +1 -0
- package/dist/transports/mcp/plan-approval.d.ts +38 -0
- package/dist/transports/mcp/plan-approval.js +175 -0
- package/dist/transports/mcp/plan-approval.js.map +1 -0
- package/dist/transports/mcp/progress-notifier.d.ts +39 -0
- package/dist/transports/mcp/progress-notifier.js +52 -0
- package/dist/transports/mcp/progress-notifier.js.map +1 -0
- package/dist/transports/mcp/session-directory.d.ts +7 -0
- package/dist/transports/mcp/session-directory.js +18 -0
- package/dist/transports/mcp/session-directory.js.map +1 -0
- package/dist/transports/mcp/tool-names.d.ts +2 -0
- package/dist/transports/mcp/tool-names.js +2 -0
- package/dist/transports/mcp/tool-names.js.map +1 -0
- package/package.json +78 -0
- package/skills/superblocks-build/SKILL.md +59 -0
- package/skills/superblocks-import/SKILL.md +88 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-card-html.js","sourceRoot":"","sources":["../../../src/transports/mcp/decision-card-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,iCAAiC,CAAC;AAC9E,MAAM,CAAC,MAAM,0BAA0B,GAAG,uBAAuB,CAAC;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAG,gCAAgC,CAAC;AAE1E,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuK/B,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA4LA,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAuYhB,4BAA4B;;sCAEnB,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGjE,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP form elicitation for Superblocks decisions (plan approve/refine and
|
|
3
|
+
* multi_choice questions).
|
|
4
|
+
*
|
|
5
|
+
* Chat is the baseline: every decision is also returned as needs_decision +
|
|
6
|
+
* decision so a host without elicitation can ask the user in its own words. A
|
|
7
|
+
* host that declares form elicitation gets a real picker instead, and the tool
|
|
8
|
+
* call answers Superblocks itself rather than handing the question back to the
|
|
9
|
+
* model.
|
|
10
|
+
*/
|
|
11
|
+
import { ElicitResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
import type { CapabilityResult, DecisionPayload } from "../../capabilities/types.js";
|
|
13
|
+
export type DecisionAnswer = {
|
|
14
|
+
kind: "answer";
|
|
15
|
+
prompt: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "approve";
|
|
18
|
+
} | {
|
|
19
|
+
feedback: string;
|
|
20
|
+
kind: "refine";
|
|
21
|
+
};
|
|
22
|
+
type EnumProperty = {
|
|
23
|
+
description?: string;
|
|
24
|
+
enum: string[];
|
|
25
|
+
enumNames?: string[];
|
|
26
|
+
title?: string;
|
|
27
|
+
type: "string";
|
|
28
|
+
};
|
|
29
|
+
type StringProperty = {
|
|
30
|
+
description?: string;
|
|
31
|
+
title?: string;
|
|
32
|
+
type: "string";
|
|
33
|
+
};
|
|
34
|
+
export type DecisionElicitationRequest = {
|
|
35
|
+
message: string;
|
|
36
|
+
mode: "form";
|
|
37
|
+
requestedSchema: {
|
|
38
|
+
properties: Record<string, EnumProperty | StringProperty>;
|
|
39
|
+
required: string[];
|
|
40
|
+
type: "object";
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
/** What a host returns from elicitation/create. */
|
|
44
|
+
type ElicitationOutcome = {
|
|
45
|
+
action: "accept" | "cancel" | "decline";
|
|
46
|
+
content?: Record<string, unknown>;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* True when the client advertised form elicitation at initialize.
|
|
50
|
+
* Empty `elicitation: {}` means form-only per the 2025-11-25 spec.
|
|
51
|
+
*/
|
|
52
|
+
export declare function clientSupportsFormElicitation(capabilities: {
|
|
53
|
+
elicitation?: Record<string, unknown>;
|
|
54
|
+
} | undefined): boolean;
|
|
55
|
+
/** The decision a capability result is waiting on, if it is waiting on one. */
|
|
56
|
+
export declare function pendingDecision(result: CapabilityResult<unknown>): DecisionPayload | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* The application a capability result was about.
|
|
59
|
+
*
|
|
60
|
+
* A tool call that named none has it resolved to the caller's recent
|
|
61
|
+
* application inside the capability, so the id the result carries is the only
|
|
62
|
+
* one a follow-up can safely key on.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resultApplicationId(result: CapabilityResult<unknown>): string | undefined;
|
|
65
|
+
export declare function resultBranch(result: CapabilityResult<unknown>): string | undefined;
|
|
66
|
+
export declare function decisionElicitationRequest(decision: DecisionPayload): DecisionElicitationRequest | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* The answer a host collected, or undefined when there is nothing to send on —
|
|
69
|
+
* a dismissed form, or an answer too incomplete to act on (refine with no
|
|
70
|
+
* feedback). Undefined means the caller should leave the decision in chat.
|
|
71
|
+
*/
|
|
72
|
+
export declare function readDecisionAnswer(decision: DecisionPayload, outcome: ElicitationOutcome): DecisionAnswer | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* How long the user gets to answer the form.
|
|
75
|
+
*
|
|
76
|
+
* The SDK would otherwise apply its own DEFAULT_REQUEST_TIMEOUT_MSEC of 60s,
|
|
77
|
+
* which expires while the picker is still on screen: the elicitation rejects,
|
|
78
|
+
* the decision falls back to chat, and the user's eventual answer lands on a
|
|
79
|
+
* request nobody is waiting for. Matched to the turn budget instead, because a
|
|
80
|
+
* turn that has run out cannot apply an answer anyway.
|
|
81
|
+
*
|
|
82
|
+
* Kept well under 2^31-1, the point at which setTimeout clamps a delay to 1ms
|
|
83
|
+
* and a nominally "never" timeout would fire immediately.
|
|
84
|
+
*/
|
|
85
|
+
export declare const DECISION_ANSWER_TIMEOUT_MS = 600000;
|
|
86
|
+
/** The slice of a tool call's `extra` that carrying a decision to the host needs. */
|
|
87
|
+
type DecisionSender = {
|
|
88
|
+
sendRequest: (request: {
|
|
89
|
+
method: "elicitation/create";
|
|
90
|
+
params: DecisionElicitationRequest;
|
|
91
|
+
}, resultSchema: typeof ElicitResultSchema, options: {
|
|
92
|
+
signal: AbortSignal;
|
|
93
|
+
timeout: number;
|
|
94
|
+
}) => Promise<ElicitationOutcome>;
|
|
95
|
+
signal: AbortSignal;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Asks the host to show the form, on the tool call's own request stream.
|
|
99
|
+
*
|
|
100
|
+
* Riding that stream matters: a request the gateway raises on its own goes to
|
|
101
|
+
* the standalone stream instead, which a host that never opened one silently
|
|
102
|
+
* drops, leaving the tool call waiting for an answer that cannot arrive.
|
|
103
|
+
*/
|
|
104
|
+
export declare function elicitDecision(extra: DecisionSender): (request: DecisionElicitationRequest) => Promise<ElicitationOutcome>;
|
|
105
|
+
/**
|
|
106
|
+
* Puts a decision to the user as a form and sends their answer on, returning
|
|
107
|
+
* the follow-up turn. Returns undefined when the decision should stay in chat,
|
|
108
|
+
* including when the host rejects the elicitation outright — an older client
|
|
109
|
+
* that declared the capability but cannot serve it must not lose the decision.
|
|
110
|
+
*/
|
|
111
|
+
export declare function resolveDecisionByElicitation(args: {
|
|
112
|
+
apply: (answer: DecisionAnswer) => Promise<CapabilityResult<unknown>>;
|
|
113
|
+
decision: DecisionPayload;
|
|
114
|
+
elicit: (request: DecisionElicitationRequest) => Promise<ElicitationOutcome>;
|
|
115
|
+
}): Promise<CapabilityResult<unknown> | undefined>;
|
|
116
|
+
export {};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP form elicitation for Superblocks decisions (plan approve/refine and
|
|
3
|
+
* multi_choice questions).
|
|
4
|
+
*
|
|
5
|
+
* Chat is the baseline: every decision is also returned as needs_decision +
|
|
6
|
+
* decision so a host without elicitation can ask the user in its own words. A
|
|
7
|
+
* host that declares form elicitation gets a real picker instead, and the tool
|
|
8
|
+
* call answers Superblocks itself rather than handing the question back to the
|
|
9
|
+
* model.
|
|
10
|
+
*/
|
|
11
|
+
import { ElicitResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
import { gatewayDebug } from "../../debug.js";
|
|
13
|
+
/**
|
|
14
|
+
* True when the client advertised form elicitation at initialize.
|
|
15
|
+
* Empty `elicitation: {}` means form-only per the 2025-11-25 spec.
|
|
16
|
+
*/
|
|
17
|
+
export function clientSupportsFormElicitation(capabilities) {
|
|
18
|
+
if (!capabilities?.elicitation) {
|
|
19
|
+
gatewayDebug("elicitation capability checked", {
|
|
20
|
+
"decision.form_supported": false,
|
|
21
|
+
"decision.reason": "capability_missing",
|
|
22
|
+
});
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const elicitation = capabilities.elicitation;
|
|
26
|
+
if (Object.keys(elicitation).length === 0) {
|
|
27
|
+
gatewayDebug("elicitation capability checked", {
|
|
28
|
+
"decision.form_supported": true,
|
|
29
|
+
"decision.reason": "empty_capability",
|
|
30
|
+
});
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const result = "form" in elicitation;
|
|
34
|
+
gatewayDebug("elicitation capability checked", {
|
|
35
|
+
"decision.form_supported": result,
|
|
36
|
+
"decision.modes": Object.keys(elicitation),
|
|
37
|
+
"decision.reason": result ? "form_advertised" : "form_missing",
|
|
38
|
+
});
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/** The decision a capability result is waiting on, if it is waiting on one. */
|
|
42
|
+
export function pendingDecision(result) {
|
|
43
|
+
if (result.kind !== "ok") {
|
|
44
|
+
gatewayDebug("pending decision checked", {
|
|
45
|
+
"decision.found": false,
|
|
46
|
+
"decision.reason": "result_error",
|
|
47
|
+
...("code" in result ? { "result.code": result.code } : {}),
|
|
48
|
+
"result.kind": result.kind,
|
|
49
|
+
});
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
if (!result.value || typeof result.value !== "object") {
|
|
53
|
+
gatewayDebug("pending decision checked", {
|
|
54
|
+
"decision.found": false,
|
|
55
|
+
"decision.reason": "result_has_no_object",
|
|
56
|
+
});
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const value = result.value;
|
|
60
|
+
const decision = value.status === "needs_decision" ? value.decision : undefined;
|
|
61
|
+
gatewayDebug("pending decision checked", {
|
|
62
|
+
"decision.found": Boolean(decision),
|
|
63
|
+
...(decision ? { "decision.kind": decision.kind } : {}),
|
|
64
|
+
"decision.reason": decision ? "waiting" : "status_not_waiting",
|
|
65
|
+
"result.status": value.status,
|
|
66
|
+
});
|
|
67
|
+
return decision;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The application a capability result was about.
|
|
71
|
+
*
|
|
72
|
+
* A tool call that named none has it resolved to the caller's recent
|
|
73
|
+
* application inside the capability, so the id the result carries is the only
|
|
74
|
+
* one a follow-up can safely key on.
|
|
75
|
+
*/
|
|
76
|
+
export function resultApplicationId(result) {
|
|
77
|
+
if (result.kind !== "ok" ||
|
|
78
|
+
!result.value ||
|
|
79
|
+
typeof result.value !== "object") {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const { applicationId } = result.value;
|
|
83
|
+
return typeof applicationId === "string" ? applicationId : undefined;
|
|
84
|
+
}
|
|
85
|
+
export function resultBranch(result) {
|
|
86
|
+
if (result.kind !== "ok" ||
|
|
87
|
+
!result.value ||
|
|
88
|
+
typeof result.value !== "object") {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const { branch } = result.value;
|
|
92
|
+
return typeof branch === "string" ? branch : undefined;
|
|
93
|
+
}
|
|
94
|
+
export function decisionElicitationRequest(decision) {
|
|
95
|
+
if (decision.kind === "missing_integrations") {
|
|
96
|
+
gatewayDebug("decision request skipped", {
|
|
97
|
+
"decision.kind": decision.kind,
|
|
98
|
+
"decision.reason": "host_action",
|
|
99
|
+
});
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
if (decision.kind === "plan") {
|
|
103
|
+
gatewayDebug("decision request created", {
|
|
104
|
+
"decision.kind": decision.kind,
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
message: decision.title
|
|
108
|
+
? `Superblocks planned "${decision.title}". Build it, or say what to change?`
|
|
109
|
+
: "Superblocks has a plan. Build it, or say what to change?",
|
|
110
|
+
mode: "form",
|
|
111
|
+
requestedSchema: {
|
|
112
|
+
properties: {
|
|
113
|
+
action: {
|
|
114
|
+
description: "Approve the plan to build it, or refine it",
|
|
115
|
+
enum: ["approve", "refine"],
|
|
116
|
+
enumNames: ["Approve — build this plan", "Refine — change it"],
|
|
117
|
+
title: "Plan",
|
|
118
|
+
type: "string",
|
|
119
|
+
},
|
|
120
|
+
feedback: {
|
|
121
|
+
description: "What to change. Required when refining.",
|
|
122
|
+
title: "Changes",
|
|
123
|
+
type: "string",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
required: ["action"],
|
|
127
|
+
type: "object",
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (decision.options.length === 0) {
|
|
132
|
+
gatewayDebug("decision request skipped", {
|
|
133
|
+
"decision.kind": decision.kind,
|
|
134
|
+
"decision.reason": "no_options",
|
|
135
|
+
});
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
gatewayDebug("decision request created", {
|
|
139
|
+
"decision.kind": decision.kind,
|
|
140
|
+
"decision.option_count": decision.options.length,
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
message: decision.question,
|
|
144
|
+
mode: "form",
|
|
145
|
+
requestedSchema: {
|
|
146
|
+
properties: {
|
|
147
|
+
choice: {
|
|
148
|
+
enum: [...decision.options],
|
|
149
|
+
title: decision.question,
|
|
150
|
+
type: "string",
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
required: ["choice"],
|
|
154
|
+
type: "object",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The answer a host collected, or undefined when there is nothing to send on —
|
|
160
|
+
* a dismissed form, or an answer too incomplete to act on (refine with no
|
|
161
|
+
* feedback). Undefined means the caller should leave the decision in chat.
|
|
162
|
+
*/
|
|
163
|
+
export function readDecisionAnswer(decision, outcome) {
|
|
164
|
+
if (decision.kind === "missing_integrations") {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
if (outcome.action !== "accept" || !outcome.content) {
|
|
168
|
+
gatewayDebug("decision answer read", {
|
|
169
|
+
"decision.answer_kind": "none",
|
|
170
|
+
"decision.kind": decision.kind,
|
|
171
|
+
"decision.reason": outcome.action,
|
|
172
|
+
});
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
if (decision.kind === "plan") {
|
|
176
|
+
const action = outcome.content.action;
|
|
177
|
+
if (action === "approve") {
|
|
178
|
+
gatewayDebug("decision answer read", {
|
|
179
|
+
"decision.answer_kind": "approve",
|
|
180
|
+
"decision.kind": decision.kind,
|
|
181
|
+
});
|
|
182
|
+
return { kind: "approve" };
|
|
183
|
+
}
|
|
184
|
+
if (action !== "refine") {
|
|
185
|
+
gatewayDebug("decision answer read", {
|
|
186
|
+
"decision.answer_kind": "none",
|
|
187
|
+
"decision.kind": decision.kind,
|
|
188
|
+
"decision.reason": "invalid_plan_action",
|
|
189
|
+
});
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const feedback = typeof outcome.content.feedback === "string"
|
|
193
|
+
? outcome.content.feedback.trim()
|
|
194
|
+
: "";
|
|
195
|
+
gatewayDebug("decision answer read", {
|
|
196
|
+
"decision.answer_kind": feedback ? "refine" : "none",
|
|
197
|
+
"decision.kind": decision.kind,
|
|
198
|
+
...(!feedback ? { "decision.reason": "missing_feedback" } : {}),
|
|
199
|
+
});
|
|
200
|
+
return feedback ? { feedback, kind: "refine" } : undefined;
|
|
201
|
+
}
|
|
202
|
+
const choice = outcome.content.choice;
|
|
203
|
+
// Only an option Superblocks offered: a free-typed answer would reach Clark
|
|
204
|
+
// as a prompt for a question it did not ask.
|
|
205
|
+
const offered = typeof choice === "string" && decision.options.includes(choice);
|
|
206
|
+
gatewayDebug("decision answer read", {
|
|
207
|
+
"decision.answer_kind": offered ? "answer" : "none",
|
|
208
|
+
"decision.kind": decision.kind,
|
|
209
|
+
...(!offered ? { "decision.reason": "choice_not_offered" } : {}),
|
|
210
|
+
});
|
|
211
|
+
return offered ? { kind: "answer", prompt: choice } : undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* How long the user gets to answer the form.
|
|
215
|
+
*
|
|
216
|
+
* The SDK would otherwise apply its own DEFAULT_REQUEST_TIMEOUT_MSEC of 60s,
|
|
217
|
+
* which expires while the picker is still on screen: the elicitation rejects,
|
|
218
|
+
* the decision falls back to chat, and the user's eventual answer lands on a
|
|
219
|
+
* request nobody is waiting for. Matched to the turn budget instead, because a
|
|
220
|
+
* turn that has run out cannot apply an answer anyway.
|
|
221
|
+
*
|
|
222
|
+
* Kept well under 2^31-1, the point at which setTimeout clamps a delay to 1ms
|
|
223
|
+
* and a nominally "never" timeout would fire immediately.
|
|
224
|
+
*/
|
|
225
|
+
export const DECISION_ANSWER_TIMEOUT_MS = 600_000;
|
|
226
|
+
/**
|
|
227
|
+
* Asks the host to show the form, on the tool call's own request stream.
|
|
228
|
+
*
|
|
229
|
+
* Riding that stream matters: a request the gateway raises on its own goes to
|
|
230
|
+
* the standalone stream instead, which a host that never opened one silently
|
|
231
|
+
* drops, leaving the tool call waiting for an answer that cannot arrive.
|
|
232
|
+
*/
|
|
233
|
+
export function elicitDecision(extra) {
|
|
234
|
+
return (request) => extra.sendRequest({ method: "elicitation/create", params: request }, ElicitResultSchema, { signal: extra.signal, timeout: DECISION_ANSWER_TIMEOUT_MS });
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Puts a decision to the user as a form and sends their answer on, returning
|
|
238
|
+
* the follow-up turn. Returns undefined when the decision should stay in chat,
|
|
239
|
+
* including when the host rejects the elicitation outright — an older client
|
|
240
|
+
* that declared the capability but cannot serve it must not lose the decision.
|
|
241
|
+
*/
|
|
242
|
+
export async function resolveDecisionByElicitation(args) {
|
|
243
|
+
const request = decisionElicitationRequest(args.decision);
|
|
244
|
+
if (!request) {
|
|
245
|
+
gatewayDebug("decision elicitation skipped", {
|
|
246
|
+
"decision.kind": args.decision.kind,
|
|
247
|
+
"decision.reason": "request_unavailable",
|
|
248
|
+
});
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
gatewayDebug("decision elicitation started", {
|
|
252
|
+
"decision.kind": args.decision.kind,
|
|
253
|
+
});
|
|
254
|
+
let outcome;
|
|
255
|
+
try {
|
|
256
|
+
outcome = await args.elicit(request);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error("gateway decision elicitation failed", error);
|
|
260
|
+
gatewayDebug("decision elicitation finished", {
|
|
261
|
+
"decision.kind": args.decision.kind,
|
|
262
|
+
"decision.reason": "host_error",
|
|
263
|
+
"decision.resolved": false,
|
|
264
|
+
});
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
gatewayDebug("decision elicitation response received", {
|
|
268
|
+
"decision.kind": args.decision.kind,
|
|
269
|
+
"decision.outcome": outcome.action,
|
|
270
|
+
});
|
|
271
|
+
const answer = readDecisionAnswer(args.decision, outcome);
|
|
272
|
+
if (!answer) {
|
|
273
|
+
gatewayDebug("decision elicitation finished", {
|
|
274
|
+
"decision.kind": args.decision.kind,
|
|
275
|
+
"decision.reason": "answer_unavailable",
|
|
276
|
+
"decision.resolved": false,
|
|
277
|
+
});
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
gatewayDebug("decision answer applying", {
|
|
281
|
+
"decision.answer_kind": answer.kind,
|
|
282
|
+
"decision.kind": args.decision.kind,
|
|
283
|
+
});
|
|
284
|
+
const result = await args.apply(answer);
|
|
285
|
+
gatewayDebug("decision elicitation finished", {
|
|
286
|
+
"decision.kind": args.decision.kind,
|
|
287
|
+
"decision.resolved": true,
|
|
288
|
+
"result.kind": result.kind,
|
|
289
|
+
});
|
|
290
|
+
return result;
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=decision-elicitation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-elicitation.js","sourceRoot":"","sources":["../../../src/transports/mcp/decision-elicitation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { AppDeps } from "../../deps.js";
|
|
3
|
+
import type { DispatchProbe } from "../../health/readiness.js";
|
|
4
|
+
/**
|
|
5
|
+
* Proves the gateway can still serve a request end to end on its own tool
|
|
6
|
+
* surface.
|
|
7
|
+
*
|
|
8
|
+
* A route handler that answers `{"status":"ok"}` proves that express is
|
|
9
|
+
* listening. It does not prove that the MCP server builds, that its tools
|
|
10
|
+
* registered, or that a JSON-RPC request can be routed to one - which is
|
|
11
|
+
* exactly the gap ENG-5809 reported: `/health` green in 1ms while every tool
|
|
12
|
+
* call timed out. This runs the real `createMcpServer` over a linked in-memory
|
|
13
|
+
* transport and asks it to list its tools, so a break anywhere in construction,
|
|
14
|
+
* registration, framing, or routing shows up as a failed probe.
|
|
15
|
+
*
|
|
16
|
+
* It deliberately stops short of invoking a tool. Every tool needs the caller's
|
|
17
|
+
* credential and reaches the platform behind the gateway, and a liveness check
|
|
18
|
+
* that fails when the platform is slow is how a healthy gateway gets restarted
|
|
19
|
+
* during someone else's outage. Upstream reachability is reported separately
|
|
20
|
+
* (see {@link GatewayReadiness}).
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMcpDispatchProbe(deps: AppDeps, options?: {
|
|
23
|
+
createServer?: () => McpServer;
|
|
24
|
+
}): DispatchProbe;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
3
|
+
import { createMcpServer } from "./mount.js";
|
|
4
|
+
/**
|
|
5
|
+
* Proves the gateway can still serve a request end to end on its own tool
|
|
6
|
+
* surface.
|
|
7
|
+
*
|
|
8
|
+
* A route handler that answers `{"status":"ok"}` proves that express is
|
|
9
|
+
* listening. It does not prove that the MCP server builds, that its tools
|
|
10
|
+
* registered, or that a JSON-RPC request can be routed to one - which is
|
|
11
|
+
* exactly the gap ENG-5809 reported: `/health` green in 1ms while every tool
|
|
12
|
+
* call timed out. This runs the real `createMcpServer` over a linked in-memory
|
|
13
|
+
* transport and asks it to list its tools, so a break anywhere in construction,
|
|
14
|
+
* registration, framing, or routing shows up as a failed probe.
|
|
15
|
+
*
|
|
16
|
+
* It deliberately stops short of invoking a tool. Every tool needs the caller's
|
|
17
|
+
* credential and reaches the platform behind the gateway, and a liveness check
|
|
18
|
+
* that fails when the platform is slow is how a healthy gateway gets restarted
|
|
19
|
+
* during someone else's outage. Upstream reachability is reported separately
|
|
20
|
+
* (see {@link GatewayReadiness}).
|
|
21
|
+
*/
|
|
22
|
+
export function createMcpDispatchProbe(deps, options = {}) {
|
|
23
|
+
const createServer = options.createServer ?? (() => createMcpServer(deps));
|
|
24
|
+
return async () => {
|
|
25
|
+
const server = createServer();
|
|
26
|
+
const client = new Client({
|
|
27
|
+
name: "gateway-dispatch-probe",
|
|
28
|
+
version: "0.0.1",
|
|
29
|
+
});
|
|
30
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
31
|
+
try {
|
|
32
|
+
await Promise.all([
|
|
33
|
+
server.connect(serverTransport),
|
|
34
|
+
client.connect(clientTransport),
|
|
35
|
+
]);
|
|
36
|
+
const { tools } = await client.listTools();
|
|
37
|
+
if (tools.length === 0) {
|
|
38
|
+
throw new Error("the gateway's MCP server registered no tools, so no call could be dispatched");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
// Every probe run gets its own server and session. Leaking either would
|
|
43
|
+
// turn a polled health endpoint into the gateway's largest consumer.
|
|
44
|
+
await Promise.allSettled([client.close(), server.close()]);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=dispatch-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-probe.js","sourceRoot":"","sources":["../../../src/transports/mcp/dispatch-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAK1E,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAa,EACb,UAA8C,EAAE;IAEhD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;YACxB,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QACH,MAAM,CAAC,eAAe,EAAE,eAAe,CAAC,GACtC,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,CAAC;gBAChB,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;gBAC/B,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;aAChC,CAAC,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;YACJ,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,wEAAwE;YACxE,qEAAqE;YACrE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const EDITOR_DOCUMENT_DEADLINE_MS = 1_000;
|
|
2
|
+
export function createEditorDocumentProbe(options = {}) {
|
|
3
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
4
|
+
return async (editUrl, signal) => {
|
|
5
|
+
if (signal?.aborted) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const controller = new AbortController();
|
|
9
|
+
const abort = () => controller.abort(signal?.reason);
|
|
10
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
11
|
+
const deadline = setTimeout(() => controller.abort(), EDITOR_DOCUMENT_DEADLINE_MS);
|
|
12
|
+
deadline.unref?.();
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetchImpl(new URL(editUrl), {
|
|
15
|
+
method: "GET",
|
|
16
|
+
redirect: "manual",
|
|
17
|
+
signal: controller.signal,
|
|
18
|
+
});
|
|
19
|
+
const available = response.ok ||
|
|
20
|
+
(response.status >= 300 && response.status < 400) ||
|
|
21
|
+
response.status === 401 ||
|
|
22
|
+
response.status === 403;
|
|
23
|
+
await response.body?.cancel().catch(() => undefined);
|
|
24
|
+
return available;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
clearTimeout(deadline);
|
|
31
|
+
signal?.removeEventListener("abort", abort);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=editor-document-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-document-probe.js","sourceRoot":"","sources":["../../../src/transports/mcp/editor-document-probe.ts"],"names":[],"mappings":"AAKA,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAE1C,MAAM,UAAU,yBAAyB,CACvC,UAAwC,EAAE;IAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;QAC/B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,CACzB,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EACxB,2BAA2B,CAC5B,CAAC;QACF,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE;gBACjD,MAAM,EAAE,KAAK;gBACb,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,MAAM,SAAS,GACb,QAAQ,CAAC,EAAE;gBACX,CAAC,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC;gBACjD,QAAQ,CAAC,MAAM,KAAK,GAAG;gBACvB,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC;YAC1B,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACrD,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { URL_PARAMS } from "@superblocksteam/library-shared";
|
|
2
|
+
export function editorIntegrationSetupUrl(input) {
|
|
3
|
+
const url = new URL(`${input.uiBaseUrl.replace(/\/$/, "")}/code-mode/applications/edit/${encodeURIComponent(input.applicationId)}`);
|
|
4
|
+
if (input.branch) {
|
|
5
|
+
url.searchParams.set("branch", input.branch);
|
|
6
|
+
}
|
|
7
|
+
url.searchParams.set(URL_PARAMS.integrationSetup, input.integrationId);
|
|
8
|
+
if (input.cowork) {
|
|
9
|
+
url.searchParams.set(URL_PARAMS.editorHost, "cowork");
|
|
10
|
+
}
|
|
11
|
+
return url.toString();
|
|
12
|
+
}
|
|
13
|
+
export function isEditorIntegrationSetupUrl(url) {
|
|
14
|
+
try {
|
|
15
|
+
const parsed = new URL(url);
|
|
16
|
+
return (parsed.pathname.includes("/applications/edit/") &&
|
|
17
|
+
parsed.searchParams.has(URL_PARAMS.integrationSetup));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=editor-integration-setup-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-integration-setup-url.js","sourceRoot":"","sources":["../../../src/transports/mcp/editor-integration-setup-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,MAAM,UAAU,yBAAyB,CAAC,KAMzC;IACC,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,gCAAgC,kBAAkB,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAC/G,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,GAAW;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,CACL,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,CAAC;YAC/C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,CACrD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ContentBlock } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { CapabilityResult } from "../../capabilities/types.js";
|
|
3
|
+
import type { ClientProfile } from "./client-presentation.js";
|
|
4
|
+
/**
|
|
5
|
+
* Serializes a capability result into MCP content blocks.
|
|
6
|
+
*
|
|
7
|
+
* Block order is important: callers read `content[0]` as the JSON body and
|
|
8
|
+
* `content.at(-1)` as the closing instruction.
|
|
9
|
+
*
|
|
10
|
+
* Screenshot bytes stay in the JSON as well as the image block, because Cursor
|
|
11
|
+
* CLI agents never see image blocks. A plan gets its own markdown block where a
|
|
12
|
+
* model renders the ask: in the JSON it is one escaped string, and a model that
|
|
13
|
+
* re-lays it out demotes headings and merges bullets. That block holds the plan
|
|
14
|
+
* and title only - an earlier version bundled instructions and option labels,
|
|
15
|
+
* which models pasted into the chat as a menu.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatMcpToolContent(result: CapabilityResult<unknown>, progress?: Array<{
|
|
18
|
+
type: string;
|
|
19
|
+
message: string;
|
|
20
|
+
}>, profile?: ClientProfile): ContentBlock[];
|