@higgsfield/video-editor-mcp 1.0.3 → 1.0.4
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/dist/index.html +244 -138
- package/dist/server.mjs +634 -262
- package/node_modules/@higgsfield/higgsedit/dist/capture-page.js +113 -39
- package/node_modules/@higgsfield/higgsedit/dist/chunk-4D6AXU4B.mjs +45 -27
- package/node_modules/@higgsfield/higgsedit/dist/chunk-C6SASQHE.mjs +130 -176
- package/node_modules/@higgsfield/higgsedit/dist/export-settings.mjs +75 -0
- package/node_modules/@higgsfield/higgsedit/dist/media-upload.mjs +381 -0
- package/node_modules/@higgsfield/higgsedit/dist/proxy.mjs +170 -0
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
package/dist/server.mjs
CHANGED
|
@@ -25742,11 +25742,11 @@ var isJSONRPCNotification = (value) => JSONRPCNotificationSchema.safeParse(value
|
|
|
25742
25742
|
var isJSONRPCResultResponse = (value) => JSONRPCResultResponseSchema.safeParse(value).success;
|
|
25743
25743
|
var isJSONRPCErrorResponse = (value) => JSONRPCErrorResponseSchema.safeParse(value).success;
|
|
25744
25744
|
var isInputRequiredResult = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && value.resultType === "input_required";
|
|
25745
|
-
function assertCompleteRequestPrompt(
|
|
25746
|
-
if (
|
|
25745
|
+
function assertCompleteRequestPrompt(request3) {
|
|
25746
|
+
if (request3.params.ref.type !== "ref/prompt") throw new TypeError(`Expected CompleteRequestPrompt, but got ${request3.params.ref.type}`);
|
|
25747
25747
|
}
|
|
25748
|
-
function assertCompleteRequestResourceTemplate(
|
|
25749
|
-
if (
|
|
25748
|
+
function assertCompleteRequestResourceTemplate(request3) {
|
|
25749
|
+
if (request3.params.ref.type !== "ref/resource") throw new TypeError(`Expected CompleteRequestResourceTemplate, but got ${request3.params.ref.type}`);
|
|
25750
25750
|
}
|
|
25751
25751
|
var X_MCP_HEADER_KEY = "x-mcp-header";
|
|
25752
25752
|
var RFC9110_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
@@ -26778,7 +26778,7 @@ var Protocol = class {
|
|
|
26778
26778
|
Promise.resolve().then(() => handler === void 0 ? fallback(notification) : handler(notification, codec2)).catch((error51) => this._onerror(/* @__PURE__ */ new Error(`Uncaught error in notification handler: ${error51}`)));
|
|
26779
26779
|
}
|
|
26780
26780
|
_onrequest(rawRequest, extra) {
|
|
26781
|
-
const { message:
|
|
26781
|
+
const { message: request3, lifted } = liftWireOnlyMaterial(rawRequest, "request");
|
|
26782
26782
|
const codec2 = this._negotiatedWireCodec();
|
|
26783
26783
|
if (extra?.classification === void 0 && this._shouldDropInbound(rawRequest) === "drop") {
|
|
26784
26784
|
this._onerror(/* @__PURE__ */ new Error(`Dropped inbound request '${rawRequest.method}': not servable on this connection's protocol era`));
|
|
@@ -26788,7 +26788,7 @@ var Protocol = class {
|
|
|
26788
26788
|
const sendErrorResponse = (code, message, data) => {
|
|
26789
26789
|
const errorResponse = {
|
|
26790
26790
|
jsonrpc: "2.0",
|
|
26791
|
-
id:
|
|
26791
|
+
id: request3.id,
|
|
26792
26792
|
error: {
|
|
26793
26793
|
code,
|
|
26794
26794
|
message,
|
|
@@ -26800,7 +26800,7 @@ var Protocol = class {
|
|
|
26800
26800
|
if (extra?.classification !== void 0) {
|
|
26801
26801
|
const classified = classifiedWireEra(extra.classification);
|
|
26802
26802
|
if (classified !== codec2.era) {
|
|
26803
|
-
this._onerror(/* @__PURE__ */ new Error(`Era mismatch on inbound request '${
|
|
26803
|
+
this._onerror(/* @__PURE__ */ new Error(`Era mismatch on inbound request '${request3.method}': classified as ${classified} but this instance serves ${codec2.era}`));
|
|
26804
26804
|
const requested = extra.classification.revision ?? classified;
|
|
26805
26805
|
sendErrorResponse(ProtocolErrorCode.UnsupportedProtocolVersion, `Unsupported protocol version: ${requested}`, {
|
|
26806
26806
|
supported: this._supportedProtocolVersions,
|
|
@@ -26809,11 +26809,11 @@ var Protocol = class {
|
|
|
26809
26809
|
return;
|
|
26810
26810
|
}
|
|
26811
26811
|
}
|
|
26812
|
-
if (isSpecRequestMethod(
|
|
26812
|
+
if (isSpecRequestMethod(request3.method) && !codec2.hasRequestMethod(request3.method)) {
|
|
26813
26813
|
sendErrorResponse(ProtocolErrorCode.MethodNotFound, "Method not found");
|
|
26814
26814
|
return;
|
|
26815
26815
|
}
|
|
26816
|
-
const handler = this._requestHandlers.get(
|
|
26816
|
+
const handler = this._requestHandlers.get(request3.method) ?? this.fallbackRequestHandler;
|
|
26817
26817
|
if (handler === void 0) {
|
|
26818
26818
|
sendErrorResponse(ProtocolErrorCode.MethodNotFound, "Method not found");
|
|
26819
26819
|
return;
|
|
@@ -26825,21 +26825,21 @@ var Protocol = class {
|
|
|
26825
26825
|
}
|
|
26826
26826
|
const sendNotification = (notification, options) => this._notificationViaCodec(this._resolveOutboundCodec(notification.method), notification, {
|
|
26827
26827
|
...options,
|
|
26828
|
-
relatedRequestId:
|
|
26828
|
+
relatedRequestId: request3.id
|
|
26829
26829
|
});
|
|
26830
26830
|
const sendRequest = (r, resultSchema, options) => this._requestWithSchemaViaCodec(this._resolveOutboundCodec(r.method), r, resultSchema, {
|
|
26831
26831
|
...options,
|
|
26832
|
-
relatedRequestId:
|
|
26832
|
+
relatedRequestId: request3.id
|
|
26833
26833
|
});
|
|
26834
26834
|
const abortController = new AbortController();
|
|
26835
|
-
this._requestHandlerAbortControllers.set(
|
|
26835
|
+
this._requestHandlerAbortControllers.set(request3.id, abortController);
|
|
26836
26836
|
const partitionedInputResponses = lifted.inputResponses === void 0 ? void 0 : partitionInputResponses(lifted.inputResponses);
|
|
26837
26837
|
const baseCtx = {
|
|
26838
26838
|
sessionId: capturedTransport?.sessionId,
|
|
26839
26839
|
mcpReq: {
|
|
26840
|
-
id:
|
|
26841
|
-
method:
|
|
26842
|
-
_meta:
|
|
26840
|
+
id: request3.id,
|
|
26841
|
+
method: request3.method,
|
|
26842
|
+
_meta: request3.params?._meta,
|
|
26843
26843
|
...lifted.envelope !== void 0 && { envelope: lifted.envelope },
|
|
26844
26844
|
...partitionedInputResponses !== void 0 && { inputResponses: partitionedInputResponses.accepted },
|
|
26845
26845
|
...partitionedInputResponses !== void 0 && partitionedInputResponses.droppedKeys.length > 0 && { droppedInputResponseKeys: partitionedInputResponses.droppedKeys },
|
|
@@ -26858,20 +26858,20 @@ var Protocol = class {
|
|
|
26858
26858
|
http: extra?.authInfo ? { authInfo: extra.authInfo } : void 0
|
|
26859
26859
|
};
|
|
26860
26860
|
const ctx = this.buildContext(baseCtx, extra);
|
|
26861
|
-
Promise.resolve().then(() => handler(
|
|
26861
|
+
Promise.resolve().then(() => handler(request3, ctx)).then(async (result) => {
|
|
26862
26862
|
if (abortController.signal.aborted) return;
|
|
26863
26863
|
let encoded;
|
|
26864
26864
|
try {
|
|
26865
|
-
encoded = codec2.encodeResult(
|
|
26865
|
+
encoded = codec2.encodeResult(request3.method, result, this._outboundServerInfo());
|
|
26866
26866
|
} catch (error51) {
|
|
26867
|
-
this._onerror(/* @__PURE__ */ new Error(`Failed to encode result for ${
|
|
26867
|
+
this._onerror(/* @__PURE__ */ new Error(`Failed to encode result for ${request3.method}: ${error51}`));
|
|
26868
26868
|
sendErrorResponse(ProtocolErrorCode.InternalError, "Internal error");
|
|
26869
26869
|
return;
|
|
26870
26870
|
}
|
|
26871
26871
|
const response = {
|
|
26872
26872
|
result: encoded,
|
|
26873
26873
|
jsonrpc: "2.0",
|
|
26874
|
-
id:
|
|
26874
|
+
id: request3.id
|
|
26875
26875
|
};
|
|
26876
26876
|
await capturedTransport?.send(response);
|
|
26877
26877
|
}, async (error51) => {
|
|
@@ -26879,7 +26879,7 @@ var Protocol = class {
|
|
|
26879
26879
|
const thrownCode = Number.isSafeInteger(error51["code"]) ? error51["code"] : ProtocolErrorCode.InternalError;
|
|
26880
26880
|
const errorResponse = {
|
|
26881
26881
|
jsonrpc: "2.0",
|
|
26882
|
-
id:
|
|
26882
|
+
id: request3.id,
|
|
26883
26883
|
error: {
|
|
26884
26884
|
code: codec2.encodeErrorCode(thrownCode),
|
|
26885
26885
|
message: error51.message ?? "Internal error",
|
|
@@ -26888,7 +26888,7 @@ var Protocol = class {
|
|
|
26888
26888
|
};
|
|
26889
26889
|
await capturedTransport?.send(errorResponse);
|
|
26890
26890
|
}).catch((error51) => this._onerror(/* @__PURE__ */ new Error(`Failed to send response: ${error51}`))).finally(() => {
|
|
26891
|
-
if (this._requestHandlerAbortControllers.get(
|
|
26891
|
+
if (this._requestHandlerAbortControllers.get(request3.id) === abortController) this._requestHandlerAbortControllers.delete(request3.id);
|
|
26892
26892
|
});
|
|
26893
26893
|
}
|
|
26894
26894
|
_onprogress(notification) {
|
|
@@ -26940,13 +26940,13 @@ var Protocol = class {
|
|
|
26940
26940
|
async close() {
|
|
26941
26941
|
await this._transport?.close();
|
|
26942
26942
|
}
|
|
26943
|
-
request(
|
|
26944
|
-
const codec2 = this._resolveOutboundCodec(
|
|
26945
|
-
this._assertOutboundRequestInEra(codec2,
|
|
26946
|
-
if (isStandardSchema(schemaOrOptions)) return this._requestWithSchemaViaCodec(codec2,
|
|
26947
|
-
const validate = codecResultValidator(codec2,
|
|
26948
|
-
if (validate === void 0) throw new TypeError(`'${
|
|
26949
|
-
return this._requestWithSchemaViaCodec(codec2,
|
|
26943
|
+
request(request3, schemaOrOptions, maybeOptions) {
|
|
26944
|
+
const codec2 = this._resolveOutboundCodec(request3.method);
|
|
26945
|
+
this._assertOutboundRequestInEra(codec2, request3.method);
|
|
26946
|
+
if (isStandardSchema(schemaOrOptions)) return this._requestWithSchemaViaCodec(codec2, request3, schemaOrOptions, maybeOptions);
|
|
26947
|
+
const validate = codecResultValidator(codec2, request3.method);
|
|
26948
|
+
if (validate === void 0) throw new TypeError(`'${request3.method}' is not a spec method; pass a result schema as the second argument to request().`);
|
|
26949
|
+
return this._requestWithSchemaViaCodec(codec2, request3, validate, schemaOrOptions);
|
|
26950
26950
|
}
|
|
26951
26951
|
/**
|
|
26952
26952
|
* The wire codec for this instance's negotiated era — the phase-2 truth:
|
|
@@ -27005,17 +27005,17 @@ var Protocol = class {
|
|
|
27005
27005
|
* explicit compatibility schemas. Spec methods are still era-gated here:
|
|
27006
27006
|
* an explicit schema never smuggles a deleted method onto the wire.
|
|
27007
27007
|
*/
|
|
27008
|
-
_requestWithSchema(
|
|
27009
|
-
const codec2 = this._resolveOutboundCodec(
|
|
27010
|
-
this._assertOutboundRequestInEra(codec2,
|
|
27011
|
-
return this._requestWithSchemaViaCodec(codec2,
|
|
27008
|
+
_requestWithSchema(request3, resultSchema, options) {
|
|
27009
|
+
const codec2 = this._resolveOutboundCodec(request3.method);
|
|
27010
|
+
this._assertOutboundRequestInEra(codec2, request3.method);
|
|
27011
|
+
return this._requestWithSchemaViaCodec(codec2, request3, resultSchema, options);
|
|
27012
27012
|
}
|
|
27013
27013
|
/**
|
|
27014
27014
|
* The request funnel proper, keyed by the resolved era codec: the codec
|
|
27015
27015
|
* owns result decoding (raw-first `resultType` discrimination — V-1 —
|
|
27016
27016
|
* and the era's lift posture) before the schema validation step.
|
|
27017
27017
|
*/
|
|
27018
|
-
_requestWithSchemaViaCodec(codec2,
|
|
27018
|
+
_requestWithSchemaViaCodec(codec2, request3, resultSchema, options) {
|
|
27019
27019
|
const { relatedRequestId, resumptionToken, onresumptiontoken, headers } = options ?? {};
|
|
27020
27020
|
const flowStartedAt = Date.now();
|
|
27021
27021
|
let onAbort;
|
|
@@ -27029,7 +27029,7 @@ var Protocol = class {
|
|
|
27029
27029
|
return;
|
|
27030
27030
|
}
|
|
27031
27031
|
if (this._options?.enforceStrictCapabilities === true) try {
|
|
27032
|
-
this.assertCapabilityForMethod(
|
|
27032
|
+
this.assertCapabilityForMethod(request3.method);
|
|
27033
27033
|
} catch (error51) {
|
|
27034
27034
|
earlyReject(error51);
|
|
27035
27035
|
return;
|
|
@@ -27042,16 +27042,16 @@ var Protocol = class {
|
|
|
27042
27042
|
const messageId = this._requestMessageId++;
|
|
27043
27043
|
cleanupMessageId = messageId;
|
|
27044
27044
|
const jsonrpcRequest = {
|
|
27045
|
-
...
|
|
27045
|
+
...request3,
|
|
27046
27046
|
jsonrpc: "2.0",
|
|
27047
27047
|
id: messageId
|
|
27048
27048
|
};
|
|
27049
27049
|
if (options?.onprogress) {
|
|
27050
27050
|
this._progressHandlers.set(messageId, options.onprogress);
|
|
27051
27051
|
jsonrpcRequest.params = {
|
|
27052
|
-
...
|
|
27052
|
+
...request3.params,
|
|
27053
27053
|
_meta: {
|
|
27054
|
-
...
|
|
27054
|
+
...request3.params?._meta,
|
|
27055
27055
|
progressToken: messageId
|
|
27056
27056
|
}
|
|
27057
27057
|
};
|
|
@@ -27082,7 +27082,7 @@ var Protocol = class {
|
|
|
27082
27082
|
if (response instanceof Error) return reject(response);
|
|
27083
27083
|
let decoded;
|
|
27084
27084
|
try {
|
|
27085
|
-
decoded = codec2.decodeResult(
|
|
27085
|
+
decoded = codec2.decodeResult(request3.method, response.result);
|
|
27086
27086
|
} catch (error51) {
|
|
27087
27087
|
return reject(error51 instanceof Error ? error51 : new Error(String(error51)));
|
|
27088
27088
|
}
|
|
@@ -27091,12 +27091,12 @@ var Protocol = class {
|
|
|
27091
27091
|
if (options?.allowInputRequired === true) return resolve3(manualInputRequiredValue(decoded));
|
|
27092
27092
|
const flow = {
|
|
27093
27093
|
codec: codec2,
|
|
27094
|
-
request:
|
|
27094
|
+
request: request3,
|
|
27095
27095
|
resultSchema,
|
|
27096
27096
|
options,
|
|
27097
27097
|
flowStartedAt,
|
|
27098
|
-
retry: (params, legOptions) => this._requestWithSchemaViaCodec(codec2, params === void 0 ? { method:
|
|
27099
|
-
method:
|
|
27098
|
+
retry: (params, legOptions) => this._requestWithSchemaViaCodec(codec2, params === void 0 ? { method: request3.method } : {
|
|
27099
|
+
method: request3.method,
|
|
27100
27100
|
params
|
|
27101
27101
|
}, resultSchema, legOptions)
|
|
27102
27102
|
};
|
|
@@ -27105,7 +27105,7 @@ var Protocol = class {
|
|
|
27105
27105
|
const result = decoded.result;
|
|
27106
27106
|
validateStandardSchema(resultSchema, result).then((parseResult) => {
|
|
27107
27107
|
if (parseResult.success) resolve3(parseResult.data);
|
|
27108
|
-
else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${
|
|
27108
|
+
else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request3.method}: ${parseResult.error}`));
|
|
27109
27109
|
}, reject);
|
|
27110
27110
|
});
|
|
27111
27111
|
onAbort = () => cancel(options?.signal?.reason);
|
|
@@ -27170,18 +27170,18 @@ var Protocol = class {
|
|
|
27170
27170
|
let stored;
|
|
27171
27171
|
if (typeof schemasOrHandler === "function") {
|
|
27172
27172
|
if (!isSpecRequestMethod(method)) throw new TypeError(`'${method}' is not a spec request method; pass schemas as the second argument to setRequestHandler().`);
|
|
27173
|
-
stored = (
|
|
27173
|
+
stored = (request3, ctx) => {
|
|
27174
27174
|
const dispatchCodec = this._negotiatedWireCodec();
|
|
27175
|
-
let outcome = dispatchCodec.validateRequest(method,
|
|
27176
|
-
if (!outcome.ok && outcome.reason === "not-in-era") outcome = dispatchCodec.validateInputRequest(method,
|
|
27175
|
+
let outcome = dispatchCodec.validateRequest(method, request3);
|
|
27176
|
+
if (!outcome.ok && outcome.reason === "not-in-era") outcome = dispatchCodec.validateInputRequest(method, request3);
|
|
27177
27177
|
if (!outcome.ok) {
|
|
27178
27178
|
if (outcome.reason === "not-in-era") throw new ProtocolError(ProtocolErrorCode.InternalError, `No wire schema for ${method} in the resolved era`);
|
|
27179
27179
|
throw new Error(outcome.message);
|
|
27180
27180
|
}
|
|
27181
27181
|
return Promise.resolve(schemasOrHandler(outcome.value, ctx));
|
|
27182
27182
|
};
|
|
27183
|
-
} else if (maybeHandler) stored = async (
|
|
27184
|
-
const parsed = await validateStandardSchema(schemasOrHandler.params, { ...
|
|
27183
|
+
} else if (maybeHandler) stored = async (request3, ctx) => {
|
|
27184
|
+
const parsed = await validateStandardSchema(schemasOrHandler.params, { ...request3.params });
|
|
27185
27185
|
if (!parsed.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid params for ${method}: ${parsed.error}`);
|
|
27186
27186
|
return maybeHandler(parsed.data, ctx);
|
|
27187
27187
|
};
|
|
@@ -34694,7 +34694,7 @@ var LegacyInputRequiredShim = class {
|
|
|
34694
34694
|
constructor(_host) {
|
|
34695
34695
|
this._host = _host;
|
|
34696
34696
|
}
|
|
34697
|
-
async fulfill(method, handler,
|
|
34697
|
+
async fulfill(method, handler, request3, ctx, firstResult) {
|
|
34698
34698
|
const { maxRounds, roundTimeoutMs } = this._host;
|
|
34699
34699
|
const outerSignal = ctx.mcpReq.signal;
|
|
34700
34700
|
let current = firstResult;
|
|
@@ -34755,7 +34755,7 @@ var LegacyInputRequiredShim = class {
|
|
|
34755
34755
|
const decoded = await this._host.verifyRequestState(requestState, ctxNext, method);
|
|
34756
34756
|
if (decoded !== void 0) ctxNext = withRequestStateValue(ctxNext, decoded);
|
|
34757
34757
|
}
|
|
34758
|
-
const next = await handler(
|
|
34758
|
+
const next = await handler(request3, ctxNext);
|
|
34759
34759
|
if (!isInputRequiredResult(next)) return next;
|
|
34760
34760
|
current = next;
|
|
34761
34761
|
}
|
|
@@ -34845,7 +34845,7 @@ var Server = class extends Protocol {
|
|
|
34845
34845
|
for (const [operation2, hint] of Object.entries(options.cacheHints)) if (hint !== void 0) assertValidCacheHint(hint, `cacheHints['${operation2}']`);
|
|
34846
34846
|
this._cacheHints = options.cacheHints;
|
|
34847
34847
|
}
|
|
34848
|
-
this.setRequestHandler("initialize", (
|
|
34848
|
+
this.setRequestHandler("initialize", (request3) => this._oninitialize(request3));
|
|
34849
34849
|
this.setNotificationHandler("notifications/initialized", () => this.oninitialized?.());
|
|
34850
34850
|
if (modernProtocolVersions(this._supportedProtocolVersions).length > 0) this.setRequestHandler("server/discover", () => this._ondiscover());
|
|
34851
34851
|
if (this._capabilities.logging) this._registerLoggingHandler();
|
|
@@ -34858,9 +34858,9 @@ var Server = class extends Protocol {
|
|
|
34858
34858
|
* Migrate to stderr logging (STDIO servers) or OpenTelemetry.
|
|
34859
34859
|
*/
|
|
34860
34860
|
_registerLoggingHandler() {
|
|
34861
|
-
this.setRequestHandler("logging/setLevel", async (
|
|
34861
|
+
this.setRequestHandler("logging/setLevel", async (request3, ctx) => {
|
|
34862
34862
|
const transportSessionId = ctx.sessionId || ctx.http?.req?.headers.get("mcp-session-id") || void 0;
|
|
34863
|
-
const { level } =
|
|
34863
|
+
const { level } = request3.params;
|
|
34864
34864
|
const parseResult = parseSchema(LoggingLevelSchema, level);
|
|
34865
34865
|
if (parseResult.success) this._loggingLevels.set(transportSessionId, parseResult.data);
|
|
34866
34866
|
return {};
|
|
@@ -34934,13 +34934,13 @@ var Server = class extends Protocol {
|
|
|
34934
34934
|
if (method !== "tools/call") {
|
|
34935
34935
|
const cacheHint = this._cacheHints?.[method];
|
|
34936
34936
|
const isInputRequiredCapable = INPUT_REQUIRED_CAPABLE_METHODS.has(method);
|
|
34937
|
-
if (cacheHint === void 0 && !isInputRequiredCapable) return async (
|
|
34938
|
-
const result = await handler(
|
|
34937
|
+
if (cacheHint === void 0 && !isInputRequiredCapable) return async (request3, ctx) => {
|
|
34938
|
+
const result = await handler(request3, ctx);
|
|
34939
34939
|
if (isInputRequiredResult(result)) throw new ProtocolError(ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but only tools/call, prompts/get and resources/read support input_required (protocol revision 2026-07-28)`);
|
|
34940
34940
|
return result;
|
|
34941
34941
|
};
|
|
34942
|
-
return async (
|
|
34943
|
-
const result = isInputRequiredCapable ? await this._invokeInputRequiredCapableHandler(method, handler,
|
|
34942
|
+
return async (request3, ctx) => {
|
|
34943
|
+
const result = isInputRequiredCapable ? await this._invokeInputRequiredCapableHandler(method, handler, request3, ctx) : await handler(request3, ctx);
|
|
34944
34944
|
if (isInputRequiredResult(result)) {
|
|
34945
34945
|
if (!isInputRequiredCapable) throw new ProtocolError(ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but only tools/call, prompts/get and resources/read support input_required (protocol revision 2026-07-28)`);
|
|
34946
34946
|
return result;
|
|
@@ -34948,11 +34948,11 @@ var Server = class extends Protocol {
|
|
|
34948
34948
|
return cacheHint === void 0 ? result : attachCacheHintFallback(result, cacheHint);
|
|
34949
34949
|
};
|
|
34950
34950
|
}
|
|
34951
|
-
return async (
|
|
34951
|
+
return async (request3, ctx) => {
|
|
34952
34952
|
const codec2 = codecForVersion(this._negotiatedProtocolVersion);
|
|
34953
|
-
const validatedRequest = codec2.validateRequest("tools/call",
|
|
34953
|
+
const validatedRequest = codec2.validateRequest("tools/call", request3);
|
|
34954
34954
|
if (!validatedRequest.ok) throw new ProtocolError(validatedRequest.reason === "not-in-era" ? ProtocolErrorCode.InternalError : ProtocolErrorCode.InvalidParams, validatedRequest.reason === "not-in-era" ? "No wire schema for tools/call in the resolved era" : `Invalid tools/call request: ${validatedRequest.message}`);
|
|
34955
|
-
const result = await this._invokeInputRequiredCapableHandler("tools/call", handler,
|
|
34955
|
+
const result = await this._invokeInputRequiredCapableHandler("tools/call", handler, request3, ctx);
|
|
34956
34956
|
if (isInputRequiredResult(result)) return result;
|
|
34957
34957
|
const normalizedResult = normalizeContentlessToolResult(result);
|
|
34958
34958
|
const validationResult = codec2.validateResult("tools/call", normalizedResult);
|
|
@@ -34990,7 +34990,7 @@ var Server = class extends Protocol {
|
|
|
34990
34990
|
* violations per family; `inputRequired.legacyShim: false` restores
|
|
34991
34991
|
* the pre-shim loud failure.
|
|
34992
34992
|
*/
|
|
34993
|
-
async _invokeInputRequiredCapableHandler(method, handler,
|
|
34993
|
+
async _invokeInputRequiredCapableHandler(method, handler, request3, ctx) {
|
|
34994
34994
|
const servedModern = this._servedModernEra();
|
|
34995
34995
|
const rawRequestState = ctx.mcpReq.requestState();
|
|
34996
34996
|
if (rawRequestState !== void 0 && typeof rawRequestState !== "string") throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Invalid or expired requestState", { reason: "invalid_request_state" });
|
|
@@ -35001,7 +35001,7 @@ var Server = class extends Protocol {
|
|
|
35001
35001
|
}
|
|
35002
35002
|
let result;
|
|
35003
35003
|
try {
|
|
35004
|
-
result = await handler(
|
|
35004
|
+
result = await handler(request3, ctxForHandler);
|
|
35005
35005
|
} catch (error51) {
|
|
35006
35006
|
if (error51 instanceof ProtocolError && error51.code === ProtocolErrorCode.UrlElicitationRequired) {
|
|
35007
35007
|
if (!servedModern) throw error51;
|
|
@@ -35012,7 +35012,7 @@ var Server = class extends Protocol {
|
|
|
35012
35012
|
if (!isInputRequiredResult(result)) return result;
|
|
35013
35013
|
if (!servedModern) {
|
|
35014
35014
|
if (!this._inputRequiredServing.legacyShim) throw new ProtocolError(ProtocolErrorCode.InternalError, `Handler for ${method} returned an input-required result, but this request is served on protocol revision ${this._negotiatedProtocolVersion ?? LATEST_PROTOCOL_VERSION}, which has no input_required vocabulary`);
|
|
35015
|
-
return await this._legacyInputRequiredShim().fulfill(method, handler,
|
|
35015
|
+
return await this._legacyInputRequiredShim().fulfill(method, handler, request3, ctxForHandler, result);
|
|
35016
35016
|
}
|
|
35017
35017
|
const inputRequests = result.inputRequests;
|
|
35018
35018
|
const hasInputRequests = inputRequests != null && Object.keys(inputRequests).length > 0;
|
|
@@ -35131,10 +35131,10 @@ var Server = class extends Protocol {
|
|
|
35131
35131
|
break;
|
|
35132
35132
|
}
|
|
35133
35133
|
}
|
|
35134
|
-
async _oninitialize(
|
|
35135
|
-
const requestedVersion =
|
|
35136
|
-
this._clientCapabilities =
|
|
35137
|
-
this._clientVersion =
|
|
35134
|
+
async _oninitialize(request3) {
|
|
35135
|
+
const requestedVersion = request3.params.protocolVersion;
|
|
35136
|
+
this._clientCapabilities = request3.params.capabilities;
|
|
35137
|
+
this._clientVersion = request3.params.clientInfo;
|
|
35138
35138
|
const legacyVersions = legacyProtocolVersions(this._supportedProtocolVersions);
|
|
35139
35139
|
const protocolVersion = legacyVersions.includes(requestedVersion) ? requestedVersion : legacyVersions[0] ?? LATEST_PROTOCOL_VERSION;
|
|
35140
35140
|
this._negotiatedProtocolVersion = protocolVersion;
|
|
@@ -35487,14 +35487,14 @@ var McpServer = class {
|
|
|
35487
35487
|
if (tool.outputSchema) toolDefinition.outputSchema = standardSchemaToJsonSchema(tool.outputSchema, "output");
|
|
35488
35488
|
return toolDefinition;
|
|
35489
35489
|
}) }));
|
|
35490
|
-
this.server.setRequestHandler("tools/call", async (
|
|
35491
|
-
const tool = this._registeredTools[
|
|
35492
|
-
if (!tool) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${
|
|
35493
|
-
if (!tool.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${
|
|
35490
|
+
this.server.setRequestHandler("tools/call", async (request3, ctx) => {
|
|
35491
|
+
const tool = this._registeredTools[request3.params.name];
|
|
35492
|
+
if (!tool) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${request3.params.name} not found`);
|
|
35493
|
+
if (!tool.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Tool ${request3.params.name} disabled`);
|
|
35494
35494
|
try {
|
|
35495
|
-
const args = await this.validateToolInput(tool,
|
|
35495
|
+
const args = await this.validateToolInput(tool, request3.params.arguments, request3.params.name);
|
|
35496
35496
|
const result = await this.executeToolHandler(tool, args, ctx);
|
|
35497
|
-
await this.validateToolOutput(tool, result,
|
|
35497
|
+
await this.validateToolOutput(tool, result, request3.params.name);
|
|
35498
35498
|
if (isInputRequiredResult(result)) return result;
|
|
35499
35499
|
return this.server.projectCallToolResult(result, tool.outputSchemaJson);
|
|
35500
35500
|
} catch (error51) {
|
|
@@ -35550,40 +35550,40 @@ var McpServer = class {
|
|
|
35550
35550
|
if (this._completionHandlerInitialized) return;
|
|
35551
35551
|
this.server.assertCanSetRequestHandler("completion/complete");
|
|
35552
35552
|
this.server.registerCapabilities({ completions: {} });
|
|
35553
|
-
this.server.setRequestHandler("completion/complete", async (
|
|
35554
|
-
switch (
|
|
35553
|
+
this.server.setRequestHandler("completion/complete", async (request3) => {
|
|
35554
|
+
switch (request3.params.ref.type) {
|
|
35555
35555
|
case "ref/prompt":
|
|
35556
|
-
assertCompleteRequestPrompt(
|
|
35557
|
-
return this.handlePromptCompletion(
|
|
35556
|
+
assertCompleteRequestPrompt(request3);
|
|
35557
|
+
return this.handlePromptCompletion(request3, request3.params.ref);
|
|
35558
35558
|
case "ref/resource":
|
|
35559
|
-
assertCompleteRequestResourceTemplate(
|
|
35560
|
-
return this.handleResourceCompletion(
|
|
35559
|
+
assertCompleteRequestResourceTemplate(request3);
|
|
35560
|
+
return this.handleResourceCompletion(request3, request3.params.ref);
|
|
35561
35561
|
default:
|
|
35562
|
-
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid completion reference: ${
|
|
35562
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid completion reference: ${request3.params.ref}`);
|
|
35563
35563
|
}
|
|
35564
35564
|
});
|
|
35565
35565
|
this._completionHandlerInitialized = true;
|
|
35566
35566
|
}
|
|
35567
|
-
async handlePromptCompletion(
|
|
35567
|
+
async handlePromptCompletion(request3, ref) {
|
|
35568
35568
|
const prompt = this._registeredPrompts[ref.name];
|
|
35569
35569
|
if (!prompt) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} not found`);
|
|
35570
35570
|
if (!prompt.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${ref.name} disabled`);
|
|
35571
35571
|
if (!prompt.argsSchema) return EMPTY_COMPLETION_RESULT;
|
|
35572
|
-
const field = unwrapOptionalSchema(getSchemaShape(prompt.argsSchema)?.[
|
|
35572
|
+
const field = unwrapOptionalSchema(getSchemaShape(prompt.argsSchema)?.[request3.params.argument.name]);
|
|
35573
35573
|
if (!isCompletable(field)) return EMPTY_COMPLETION_RESULT;
|
|
35574
35574
|
const completer = getCompleter(field);
|
|
35575
35575
|
if (!completer) return EMPTY_COMPLETION_RESULT;
|
|
35576
|
-
return createCompletionResult(await completer(
|
|
35576
|
+
return createCompletionResult(await completer(request3.params.argument.value, request3.params.context));
|
|
35577
35577
|
}
|
|
35578
|
-
async handleResourceCompletion(
|
|
35578
|
+
async handleResourceCompletion(request3, ref) {
|
|
35579
35579
|
const template = Object.values(this._registeredResourceTemplates).find((t) => t.resourceTemplate.uriTemplate.toString() === ref.uri);
|
|
35580
35580
|
if (!template) {
|
|
35581
35581
|
if (this._registeredResources[ref.uri]) return EMPTY_COMPLETION_RESULT;
|
|
35582
|
-
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource template ${
|
|
35582
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource template ${request3.params.ref.uri} not found`);
|
|
35583
35583
|
}
|
|
35584
|
-
const completer = template.resourceTemplate.completeCallback(
|
|
35584
|
+
const completer = template.resourceTemplate.completeCallback(request3.params.argument.name);
|
|
35585
35585
|
if (!completer) return EMPTY_COMPLETION_RESULT;
|
|
35586
|
-
return createCompletionResult(await completer(
|
|
35586
|
+
return createCompletionResult(await completer(request3.params.argument.value, request3.params.context));
|
|
35587
35587
|
}
|
|
35588
35588
|
_resourceHandlersInitialized = false;
|
|
35589
35589
|
setResourceRequestHandlers() {
|
|
@@ -35616,13 +35616,13 @@ var McpServer = class {
|
|
|
35616
35616
|
...template.metadata
|
|
35617
35617
|
})) };
|
|
35618
35618
|
});
|
|
35619
|
-
this.server.setRequestHandler("resources/read", async (
|
|
35619
|
+
this.server.setRequestHandler("resources/read", async (request3, ctx) => {
|
|
35620
35620
|
let uri;
|
|
35621
35621
|
try {
|
|
35622
|
-
uri = new URL(
|
|
35622
|
+
uri = new URL(request3.params.uri);
|
|
35623
35623
|
} catch {
|
|
35624
|
-
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource URI ${
|
|
35625
|
-
uri:
|
|
35624
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource URI ${request3.params.uri} is invalid`, {
|
|
35625
|
+
uri: request3.params.uri,
|
|
35626
35626
|
reason: "invalid_uri"
|
|
35627
35627
|
});
|
|
35628
35628
|
}
|
|
@@ -35635,7 +35635,7 @@ var McpServer = class {
|
|
|
35635
35635
|
const variables = template.resourceTemplate.uriTemplate.match(uri.toString());
|
|
35636
35636
|
if (variables) return attachCacheHintFallback(await template.readCallback(uri, variables, ctx), template.cacheHint);
|
|
35637
35637
|
}
|
|
35638
|
-
throw new ResourceNotFoundError(
|
|
35638
|
+
throw new ResourceNotFoundError(request3.params.uri);
|
|
35639
35639
|
});
|
|
35640
35640
|
this._resourceHandlersInitialized = true;
|
|
35641
35641
|
}
|
|
@@ -35655,11 +35655,11 @@ var McpServer = class {
|
|
|
35655
35655
|
_meta: prompt._meta
|
|
35656
35656
|
};
|
|
35657
35657
|
}) }));
|
|
35658
|
-
this.server.setRequestHandler("prompts/get", async (
|
|
35659
|
-
const prompt = this._registeredPrompts[
|
|
35660
|
-
if (!prompt) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${
|
|
35661
|
-
if (!prompt.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${
|
|
35662
|
-
return prompt.handler(
|
|
35658
|
+
this.server.setRequestHandler("prompts/get", async (request3, ctx) => {
|
|
35659
|
+
const prompt = this._registeredPrompts[request3.params.name];
|
|
35660
|
+
if (!prompt) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${request3.params.name} not found`);
|
|
35661
|
+
if (!prompt.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Prompt ${request3.params.name} disabled`);
|
|
35662
|
+
return prompt.handler(request3.params.arguments, ctx);
|
|
35663
35663
|
});
|
|
35664
35664
|
this._promptHandlersInitialized = true;
|
|
35665
35665
|
}
|
|
@@ -36260,7 +36260,7 @@ function serveStdio(factory, options = {}) {
|
|
|
36260
36260
|
}
|
|
36261
36261
|
return false;
|
|
36262
36262
|
};
|
|
36263
|
-
const answerLegacyRejection = (
|
|
36263
|
+
const answerLegacyRejection = (request3, reason, requestedVersion) => {
|
|
36264
36264
|
const rejection2 = modernOnlyStrictRejection({
|
|
36265
36265
|
kind: "legacy",
|
|
36266
36266
|
reason,
|
|
@@ -36268,7 +36268,7 @@ function serveStdio(factory, options = {}) {
|
|
|
36268
36268
|
}, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
36269
36269
|
if (rejection2 === void 0) return Promise.resolve();
|
|
36270
36270
|
reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection2.cell}): ${rejection2.message}`));
|
|
36271
|
-
return writeErrorResponse(
|
|
36271
|
+
return writeErrorResponse(request3.id, rejection2.code, rejection2.message, rejection2.data);
|
|
36272
36272
|
};
|
|
36273
36273
|
const onInstanceClosed = (channel) => {
|
|
36274
36274
|
if (closing || channel === discarding) return;
|
|
@@ -38102,8 +38102,8 @@ var Protocol2 = class {
|
|
|
38102
38102
|
this._taskStore = _options?.taskStore;
|
|
38103
38103
|
this._taskMessageQueue = _options?.taskMessageQueue;
|
|
38104
38104
|
if (this._taskStore) {
|
|
38105
|
-
this.setRequestHandler(GetTaskRequestSchema2, async (
|
|
38106
|
-
const task = await this._taskStore.getTask(
|
|
38105
|
+
this.setRequestHandler(GetTaskRequestSchema2, async (request3, extra) => {
|
|
38106
|
+
const task = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
|
|
38107
38107
|
if (!task) {
|
|
38108
38108
|
throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
|
|
38109
38109
|
}
|
|
@@ -38111,9 +38111,9 @@ var Protocol2 = class {
|
|
|
38111
38111
|
...task
|
|
38112
38112
|
};
|
|
38113
38113
|
});
|
|
38114
|
-
this.setRequestHandler(GetTaskPayloadRequestSchema2, async (
|
|
38114
|
+
this.setRequestHandler(GetTaskPayloadRequestSchema2, async (request3, extra) => {
|
|
38115
38115
|
const handleTaskResult = async () => {
|
|
38116
|
-
const taskId =
|
|
38116
|
+
const taskId = request3.params.taskId;
|
|
38117
38117
|
if (this._taskMessageQueue) {
|
|
38118
38118
|
let queuedMessage;
|
|
38119
38119
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -38164,9 +38164,9 @@ var Protocol2 = class {
|
|
|
38164
38164
|
};
|
|
38165
38165
|
return await handleTaskResult();
|
|
38166
38166
|
});
|
|
38167
|
-
this.setRequestHandler(ListTasksRequestSchema2, async (
|
|
38167
|
+
this.setRequestHandler(ListTasksRequestSchema2, async (request3, extra) => {
|
|
38168
38168
|
try {
|
|
38169
|
-
const { tasks, nextCursor } = await this._taskStore.listTasks(
|
|
38169
|
+
const { tasks, nextCursor } = await this._taskStore.listTasks(request3.params?.cursor, extra.sessionId);
|
|
38170
38170
|
return {
|
|
38171
38171
|
tasks,
|
|
38172
38172
|
nextCursor,
|
|
@@ -38176,20 +38176,20 @@ var Protocol2 = class {
|
|
|
38176
38176
|
throw new McpError(ErrorCode.InvalidParams, `Failed to list tasks: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
38177
38177
|
}
|
|
38178
38178
|
});
|
|
38179
|
-
this.setRequestHandler(CancelTaskRequestSchema2, async (
|
|
38179
|
+
this.setRequestHandler(CancelTaskRequestSchema2, async (request3, extra) => {
|
|
38180
38180
|
try {
|
|
38181
|
-
const task = await this._taskStore.getTask(
|
|
38181
|
+
const task = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
|
|
38182
38182
|
if (!task) {
|
|
38183
|
-
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${
|
|
38183
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request3.params.taskId}`);
|
|
38184
38184
|
}
|
|
38185
38185
|
if (isTerminal(task.status)) {
|
|
38186
38186
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
38187
38187
|
}
|
|
38188
|
-
await this._taskStore.updateTaskStatus(
|
|
38189
|
-
this._clearTaskQueue(
|
|
38190
|
-
const cancelledTask = await this._taskStore.getTask(
|
|
38188
|
+
await this._taskStore.updateTaskStatus(request3.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
38189
|
+
this._clearTaskQueue(request3.params.taskId);
|
|
38190
|
+
const cancelledTask = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
|
|
38191
38191
|
if (!cancelledTask) {
|
|
38192
|
-
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${
|
|
38192
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request3.params.taskId}`);
|
|
38193
38193
|
}
|
|
38194
38194
|
return {
|
|
38195
38195
|
_meta: {},
|
|
@@ -38310,14 +38310,14 @@ var Protocol2 = class {
|
|
|
38310
38310
|
}
|
|
38311
38311
|
Promise.resolve().then(() => handler(notification)).catch((error51) => this._onerror(new Error(`Uncaught error in notification handler: ${error51}`)));
|
|
38312
38312
|
}
|
|
38313
|
-
_onrequest(
|
|
38314
|
-
const handler = this._requestHandlers.get(
|
|
38313
|
+
_onrequest(request3, extra) {
|
|
38314
|
+
const handler = this._requestHandlers.get(request3.method) ?? this.fallbackRequestHandler;
|
|
38315
38315
|
const capturedTransport = this._transport;
|
|
38316
|
-
const relatedTaskId =
|
|
38316
|
+
const relatedTaskId = request3.params?._meta?.[RELATED_TASK_META_KEY2]?.taskId;
|
|
38317
38317
|
if (handler === void 0) {
|
|
38318
38318
|
const errorResponse = {
|
|
38319
38319
|
jsonrpc: "2.0",
|
|
38320
|
-
id:
|
|
38320
|
+
id: request3.id,
|
|
38321
38321
|
error: {
|
|
38322
38322
|
code: ErrorCode.MethodNotFound,
|
|
38323
38323
|
message: "Method not found"
|
|
@@ -38335,17 +38335,17 @@ var Protocol2 = class {
|
|
|
38335
38335
|
return;
|
|
38336
38336
|
}
|
|
38337
38337
|
const abortController = new AbortController();
|
|
38338
|
-
this._requestHandlerAbortControllers.set(
|
|
38339
|
-
const taskCreationParams = isTaskAugmentedRequestParams2(
|
|
38340
|
-
const taskStore = this._taskStore ? this.requestTaskStore(
|
|
38338
|
+
this._requestHandlerAbortControllers.set(request3.id, abortController);
|
|
38339
|
+
const taskCreationParams = isTaskAugmentedRequestParams2(request3.params) ? request3.params.task : void 0;
|
|
38340
|
+
const taskStore = this._taskStore ? this.requestTaskStore(request3, capturedTransport?.sessionId) : void 0;
|
|
38341
38341
|
const fullExtra = {
|
|
38342
38342
|
signal: abortController.signal,
|
|
38343
38343
|
sessionId: capturedTransport?.sessionId,
|
|
38344
|
-
_meta:
|
|
38344
|
+
_meta: request3.params?._meta,
|
|
38345
38345
|
sendNotification: async (notification) => {
|
|
38346
38346
|
if (abortController.signal.aborted)
|
|
38347
38347
|
return;
|
|
38348
|
-
const notificationOptions = { relatedRequestId:
|
|
38348
|
+
const notificationOptions = { relatedRequestId: request3.id };
|
|
38349
38349
|
if (relatedTaskId) {
|
|
38350
38350
|
notificationOptions.relatedTask = { taskId: relatedTaskId };
|
|
38351
38351
|
}
|
|
@@ -38355,7 +38355,7 @@ var Protocol2 = class {
|
|
|
38355
38355
|
if (abortController.signal.aborted) {
|
|
38356
38356
|
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
38357
38357
|
}
|
|
38358
|
-
const requestOptions = { ...options, relatedRequestId:
|
|
38358
|
+
const requestOptions = { ...options, relatedRequestId: request3.id };
|
|
38359
38359
|
if (relatedTaskId && !requestOptions.relatedTask) {
|
|
38360
38360
|
requestOptions.relatedTask = { taskId: relatedTaskId };
|
|
38361
38361
|
}
|
|
@@ -38366,7 +38366,7 @@ var Protocol2 = class {
|
|
|
38366
38366
|
return await this.request(r, resultSchema, requestOptions);
|
|
38367
38367
|
},
|
|
38368
38368
|
authInfo: extra?.authInfo,
|
|
38369
|
-
requestId:
|
|
38369
|
+
requestId: request3.id,
|
|
38370
38370
|
requestInfo: extra?.requestInfo,
|
|
38371
38371
|
taskId: relatedTaskId,
|
|
38372
38372
|
taskStore,
|
|
@@ -38376,16 +38376,16 @@ var Protocol2 = class {
|
|
|
38376
38376
|
};
|
|
38377
38377
|
Promise.resolve().then(() => {
|
|
38378
38378
|
if (taskCreationParams) {
|
|
38379
|
-
this.assertTaskHandlerCapability(
|
|
38379
|
+
this.assertTaskHandlerCapability(request3.method);
|
|
38380
38380
|
}
|
|
38381
|
-
}).then(() => handler(
|
|
38381
|
+
}).then(() => handler(request3, fullExtra)).then(async (result) => {
|
|
38382
38382
|
if (abortController.signal.aborted) {
|
|
38383
38383
|
return;
|
|
38384
38384
|
}
|
|
38385
38385
|
const response = {
|
|
38386
38386
|
result,
|
|
38387
38387
|
jsonrpc: "2.0",
|
|
38388
|
-
id:
|
|
38388
|
+
id: request3.id
|
|
38389
38389
|
};
|
|
38390
38390
|
if (relatedTaskId && this._taskMessageQueue) {
|
|
38391
38391
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
@@ -38402,7 +38402,7 @@ var Protocol2 = class {
|
|
|
38402
38402
|
}
|
|
38403
38403
|
const errorResponse = {
|
|
38404
38404
|
jsonrpc: "2.0",
|
|
38405
|
-
id:
|
|
38405
|
+
id: request3.id,
|
|
38406
38406
|
error: {
|
|
38407
38407
|
code: Number.isSafeInteger(error51["code"]) ? error51["code"] : ErrorCode.InternalError,
|
|
38408
38408
|
message: error51.message ?? "Internal error",
|
|
@@ -38419,8 +38419,8 @@ var Protocol2 = class {
|
|
|
38419
38419
|
await capturedTransport?.send(errorResponse);
|
|
38420
38420
|
}
|
|
38421
38421
|
}).catch((error51) => this._onerror(new Error(`Failed to send response: ${error51}`))).finally(() => {
|
|
38422
|
-
if (this._requestHandlerAbortControllers.get(
|
|
38423
|
-
this._requestHandlerAbortControllers.delete(
|
|
38422
|
+
if (this._requestHandlerAbortControllers.get(request3.id) === abortController) {
|
|
38423
|
+
this._requestHandlerAbortControllers.delete(request3.id);
|
|
38424
38424
|
}
|
|
38425
38425
|
});
|
|
38426
38426
|
}
|
|
@@ -38524,11 +38524,11 @@ var Protocol2 = class {
|
|
|
38524
38524
|
*
|
|
38525
38525
|
* @experimental Use `client.experimental.tasks.requestStream()` to access this method.
|
|
38526
38526
|
*/
|
|
38527
|
-
async *requestStream(
|
|
38527
|
+
async *requestStream(request3, resultSchema, options) {
|
|
38528
38528
|
const { task } = options ?? {};
|
|
38529
38529
|
if (!task) {
|
|
38530
38530
|
try {
|
|
38531
|
-
const result = await this.request(
|
|
38531
|
+
const result = await this.request(request3, resultSchema, options);
|
|
38532
38532
|
yield { type: "result", result };
|
|
38533
38533
|
} catch (error51) {
|
|
38534
38534
|
yield {
|
|
@@ -38540,7 +38540,7 @@ var Protocol2 = class {
|
|
|
38540
38540
|
}
|
|
38541
38541
|
let taskId;
|
|
38542
38542
|
try {
|
|
38543
|
-
const createResult = await this.request(
|
|
38543
|
+
const createResult = await this.request(request3, CreateTaskResultSchema2, options);
|
|
38544
38544
|
if (createResult.task) {
|
|
38545
38545
|
taskId = createResult.task.taskId;
|
|
38546
38546
|
yield { type: "taskCreated", task: createResult.task };
|
|
@@ -38588,7 +38588,7 @@ var Protocol2 = class {
|
|
|
38588
38588
|
*
|
|
38589
38589
|
* Do not use this method to emit notifications! Use notification() instead.
|
|
38590
38590
|
*/
|
|
38591
|
-
request(
|
|
38591
|
+
request(request3, resultSchema, options) {
|
|
38592
38592
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
38593
38593
|
return new Promise((resolve3, reject) => {
|
|
38594
38594
|
const earlyReject = (error51) => {
|
|
@@ -38600,9 +38600,9 @@ var Protocol2 = class {
|
|
|
38600
38600
|
}
|
|
38601
38601
|
if (this._options?.enforceStrictCapabilities === true) {
|
|
38602
38602
|
try {
|
|
38603
|
-
this.assertCapabilityForMethod(
|
|
38603
|
+
this.assertCapabilityForMethod(request3.method);
|
|
38604
38604
|
if (task) {
|
|
38605
|
-
this.assertTaskCapability(
|
|
38605
|
+
this.assertTaskCapability(request3.method);
|
|
38606
38606
|
}
|
|
38607
38607
|
} catch (e) {
|
|
38608
38608
|
earlyReject(e);
|
|
@@ -38612,16 +38612,16 @@ var Protocol2 = class {
|
|
|
38612
38612
|
options?.signal?.throwIfAborted();
|
|
38613
38613
|
const messageId = this._requestMessageId++;
|
|
38614
38614
|
const jsonrpcRequest = {
|
|
38615
|
-
...
|
|
38615
|
+
...request3,
|
|
38616
38616
|
jsonrpc: "2.0",
|
|
38617
38617
|
id: messageId
|
|
38618
38618
|
};
|
|
38619
38619
|
if (options?.onprogress) {
|
|
38620
38620
|
this._progressHandlers.set(messageId, options.onprogress);
|
|
38621
38621
|
jsonrpcRequest.params = {
|
|
38622
|
-
...
|
|
38622
|
+
...request3.params,
|
|
38623
38623
|
_meta: {
|
|
38624
|
-
...
|
|
38624
|
+
...request3.params?._meta || {},
|
|
38625
38625
|
progressToken: messageId
|
|
38626
38626
|
}
|
|
38627
38627
|
};
|
|
@@ -38825,8 +38825,8 @@ var Protocol2 = class {
|
|
|
38825
38825
|
setRequestHandler(requestSchema, handler) {
|
|
38826
38826
|
const method = getMethodLiteral(requestSchema);
|
|
38827
38827
|
this.assertRequestHandlerCapability(method);
|
|
38828
|
-
this._requestHandlers.set(method, (
|
|
38829
|
-
const parsed = parseWithCompat(requestSchema,
|
|
38828
|
+
this._requestHandlers.set(method, (request3, extra) => {
|
|
38829
|
+
const parsed = parseWithCompat(requestSchema, request3);
|
|
38830
38830
|
return Promise.resolve(handler(parsed, extra));
|
|
38831
38831
|
});
|
|
38832
38832
|
}
|
|
@@ -38941,19 +38941,19 @@ var Protocol2 = class {
|
|
|
38941
38941
|
}, { once: true });
|
|
38942
38942
|
});
|
|
38943
38943
|
}
|
|
38944
|
-
requestTaskStore(
|
|
38944
|
+
requestTaskStore(request3, sessionId) {
|
|
38945
38945
|
const taskStore = this._taskStore;
|
|
38946
38946
|
if (!taskStore) {
|
|
38947
38947
|
throw new Error("No task store configured");
|
|
38948
38948
|
}
|
|
38949
38949
|
return {
|
|
38950
38950
|
createTask: async (taskParams) => {
|
|
38951
|
-
if (!
|
|
38951
|
+
if (!request3) {
|
|
38952
38952
|
throw new Error("No request provided");
|
|
38953
38953
|
}
|
|
38954
|
-
return await taskStore.createTask(taskParams,
|
|
38955
|
-
method:
|
|
38956
|
-
params:
|
|
38954
|
+
return await taskStore.createTask(taskParams, request3.id, {
|
|
38955
|
+
method: request3.method,
|
|
38956
|
+
params: request3.params
|
|
38957
38957
|
}, sessionId);
|
|
38958
38958
|
},
|
|
38959
38959
|
getTask: async (taskId) => {
|
|
@@ -39244,8 +39244,8 @@ var ExperimentalClientTasks = class {
|
|
|
39244
39244
|
*
|
|
39245
39245
|
* @experimental
|
|
39246
39246
|
*/
|
|
39247
|
-
requestStream(
|
|
39248
|
-
return this._client.requestStream(
|
|
39247
|
+
requestStream(request3, resultSchema, options) {
|
|
39248
|
+
return this._client.requestStream(request3, resultSchema, options);
|
|
39249
39249
|
}
|
|
39250
39250
|
};
|
|
39251
39251
|
|
|
@@ -39410,8 +39410,8 @@ var Client = class extends Protocol2 {
|
|
|
39410
39410
|
}
|
|
39411
39411
|
const method = methodValue;
|
|
39412
39412
|
if (method === "elicitation/create") {
|
|
39413
|
-
const wrappedHandler = async (
|
|
39414
|
-
const validatedRequest = safeParse3(ElicitRequestSchema2,
|
|
39413
|
+
const wrappedHandler = async (request3, extra) => {
|
|
39414
|
+
const validatedRequest = safeParse3(ElicitRequestSchema2, request3);
|
|
39415
39415
|
if (!validatedRequest.success) {
|
|
39416
39416
|
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
39417
39417
|
throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
|
|
@@ -39425,7 +39425,7 @@ var Client = class extends Protocol2 {
|
|
|
39425
39425
|
if (params.mode === "url" && !supportsUrlMode) {
|
|
39426
39426
|
throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
|
|
39427
39427
|
}
|
|
39428
|
-
const result = await Promise.resolve(handler(
|
|
39428
|
+
const result = await Promise.resolve(handler(request3, extra));
|
|
39429
39429
|
if (params.task) {
|
|
39430
39430
|
const taskValidationResult = safeParse3(CreateTaskResultSchema2, result);
|
|
39431
39431
|
if (!taskValidationResult.success) {
|
|
@@ -39454,14 +39454,14 @@ var Client = class extends Protocol2 {
|
|
|
39454
39454
|
return super.setRequestHandler(requestSchema, wrappedHandler);
|
|
39455
39455
|
}
|
|
39456
39456
|
if (method === "sampling/createMessage") {
|
|
39457
|
-
const wrappedHandler = async (
|
|
39458
|
-
const validatedRequest = safeParse3(CreateMessageRequestSchema2,
|
|
39457
|
+
const wrappedHandler = async (request3, extra) => {
|
|
39458
|
+
const validatedRequest = safeParse3(CreateMessageRequestSchema2, request3);
|
|
39459
39459
|
if (!validatedRequest.success) {
|
|
39460
39460
|
const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
39461
39461
|
throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
|
|
39462
39462
|
}
|
|
39463
39463
|
const { params } = validatedRequest.data;
|
|
39464
|
-
const result = await Promise.resolve(handler(
|
|
39464
|
+
const result = await Promise.resolve(handler(request3, extra));
|
|
39465
39465
|
if (params.task) {
|
|
39466
39466
|
const taskValidationResult = safeParse3(CreateTaskResultSchema2, result);
|
|
39467
39467
|
if (!taskValidationResult.success) {
|
|
@@ -41006,13 +41006,13 @@ var StreamableHTTPClientTransport = class {
|
|
|
41006
41006
|
this.onerror?.(new Error(`Maximum reconnection attempts (${maxRetries}) exceeded.`));
|
|
41007
41007
|
return;
|
|
41008
41008
|
}
|
|
41009
|
-
const
|
|
41009
|
+
const delay2 = this._getNextReconnectionDelay(attemptCount);
|
|
41010
41010
|
this._reconnectionTimeout = setTimeout(() => {
|
|
41011
41011
|
this._startOrAuthSse(options).catch((error51) => {
|
|
41012
41012
|
this.onerror?.(new Error(`Failed to reconnect SSE stream: ${error51 instanceof Error ? error51.message : String(error51)}`));
|
|
41013
41013
|
this._scheduleReconnection(options, attemptCount + 1);
|
|
41014
41014
|
});
|
|
41015
|
-
},
|
|
41015
|
+
}, delay2);
|
|
41016
41016
|
}
|
|
41017
41017
|
_handleSseStream(stream, options, isReconnectable) {
|
|
41018
41018
|
if (!stream) {
|
|
@@ -41572,7 +41572,7 @@ function registerHostedProxyTools(server, url2, session = new LocalBrowserSessio
|
|
|
41572
41572
|
const previous = connected?.client;
|
|
41573
41573
|
const next = new Client({
|
|
41574
41574
|
name: "higgsfield-video-editor-local",
|
|
41575
|
-
version: "1.0.
|
|
41575
|
+
version: "1.0.4"
|
|
41576
41576
|
});
|
|
41577
41577
|
const transport = new StreamableHTTPClientTransport(new URL(url2), {
|
|
41578
41578
|
requestInit: { headers: { Authorization: `Bearer ${token}` } }
|
|
@@ -41746,7 +41746,7 @@ async function projectName(directory, root, update) {
|
|
|
41746
41746
|
|
|
41747
41747
|
// src/tools/video-editor-local/index.ts
|
|
41748
41748
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
41749
|
-
import { appendFile
|
|
41749
|
+
import { appendFile, link as link3, mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile6, rm as rm5, stat as stat3, writeFile as writeFile6 } from "node:fs/promises";
|
|
41750
41750
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
41751
41751
|
import { basename as basename2, extname, isAbsolute as isAbsolute2, join as join9, relative as relative2, resolve as resolve2 } from "node:path";
|
|
41752
41752
|
import { execFile as execFile3 } from "node:child_process";
|
|
@@ -41822,7 +41822,7 @@ var cspOrigins = [];
|
|
|
41822
41822
|
var directCspOrigins = () => cspOrigins;
|
|
41823
41823
|
var CORS = {
|
|
41824
41824
|
"access-control-allow-origin": "*",
|
|
41825
|
-
"access-control-allow-methods": "GET, HEAD, POST, OPTIONS",
|
|
41825
|
+
"access-control-allow-methods": "GET, HEAD, POST, PUT, DELETE, OPTIONS",
|
|
41826
41826
|
"access-control-allow-headers": "range, content-type",
|
|
41827
41827
|
"access-control-expose-headers": "content-range, content-length, accept-ranges, content-type",
|
|
41828
41828
|
// An https page reaching loopback (Private Network Access / Local Network Access preflights).
|
|
@@ -41935,6 +41935,149 @@ var DirectServer = class {
|
|
|
41935
41935
|
}
|
|
41936
41936
|
};
|
|
41937
41937
|
|
|
41938
|
+
// src/shared/video-editor-media-import.ts
|
|
41939
|
+
var STREAMING_MEDIA_PATH = "api/media/stream";
|
|
41940
|
+
var STREAMING_IMPORT_REQUIRED = "This project is still using an older editor backend. Finish its running work, stop that higgsedit dev process, and reopen the project with the updated plugin before importing media.";
|
|
41941
|
+
|
|
41942
|
+
// src/tools/video-editor-local/import-media.ts
|
|
41943
|
+
var REDIRECTS = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
41944
|
+
function httpsUrl(value) {
|
|
41945
|
+
const url2 = new URL(value);
|
|
41946
|
+
if (url2.protocol !== "https:") throw new Error("Only https URLs can be imported.");
|
|
41947
|
+
return url2;
|
|
41948
|
+
}
|
|
41949
|
+
async function download(fetcher, start, signal) {
|
|
41950
|
+
let url2 = start;
|
|
41951
|
+
for (let redirects = 0; redirects <= 5; redirects++) {
|
|
41952
|
+
const response = await fetcher(url2, { signal, redirect: "manual" });
|
|
41953
|
+
if (!REDIRECTS.has(response.status)) return response;
|
|
41954
|
+
await response.body?.cancel();
|
|
41955
|
+
const location = response.headers.get("location");
|
|
41956
|
+
if (!location) throw new Error("Download redirect is missing its destination.");
|
|
41957
|
+
url2 = httpsUrl(new URL(location, url2).href);
|
|
41958
|
+
}
|
|
41959
|
+
throw new Error("Download has too many redirects.");
|
|
41960
|
+
}
|
|
41961
|
+
async function uploadResult(response) {
|
|
41962
|
+
if (response.status === 404) {
|
|
41963
|
+
await response.body?.cancel();
|
|
41964
|
+
throw new Error(STREAMING_IMPORT_REQUIRED);
|
|
41965
|
+
}
|
|
41966
|
+
if (!response.body)
|
|
41967
|
+
throw new Error(`Media upload returned an empty response (${response.status}).`);
|
|
41968
|
+
const reader = response.body.getReader();
|
|
41969
|
+
const decoder = new TextDecoder();
|
|
41970
|
+
let text = "";
|
|
41971
|
+
let size = 0;
|
|
41972
|
+
try {
|
|
41973
|
+
for (; ; ) {
|
|
41974
|
+
const { value, done } = await reader.read();
|
|
41975
|
+
if (done) break;
|
|
41976
|
+
size += value.byteLength;
|
|
41977
|
+
if (size > 64 * 1024) throw new Error("Media upload response exceeds 64 KiB.");
|
|
41978
|
+
text += decoder.decode(value, { stream: true });
|
|
41979
|
+
}
|
|
41980
|
+
text += decoder.decode();
|
|
41981
|
+
} finally {
|
|
41982
|
+
await reader.cancel().catch(() => void 0);
|
|
41983
|
+
reader.releaseLock();
|
|
41984
|
+
}
|
|
41985
|
+
let result;
|
|
41986
|
+
try {
|
|
41987
|
+
result = JSON.parse(text);
|
|
41988
|
+
} catch {
|
|
41989
|
+
throw new Error(`Media upload returned invalid JSON (${response.status}).`);
|
|
41990
|
+
}
|
|
41991
|
+
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
41992
|
+
throw new Error("Media upload returned an invalid result.");
|
|
41993
|
+
const object3 = result;
|
|
41994
|
+
if (!response.ok)
|
|
41995
|
+
throw new Error(
|
|
41996
|
+
typeof object3.error === "string" ? object3.error.slice(0, 1e3) : `Media upload failed (${response.status}).`
|
|
41997
|
+
);
|
|
41998
|
+
return object3;
|
|
41999
|
+
}
|
|
42000
|
+
async function importMedia(origin, url2, fileName, signal, options = {}) {
|
|
42001
|
+
const parsed = httpsUrl(url2);
|
|
42002
|
+
const name = (fileName ?? decodeURIComponent(parsed.pathname.split("/").at(-1) ?? "")).replace(/[/\\]/g, "_").replace(/^\.+/, "") || "import";
|
|
42003
|
+
if (/\0/.test(name)) throw new Error("The media file name contains a null character.");
|
|
42004
|
+
const endpoint = new URL(`/${STREAMING_MEDIA_PATH}`, origin);
|
|
42005
|
+
endpoint.searchParams.set("name", name);
|
|
42006
|
+
const controller = new AbortController();
|
|
42007
|
+
const abort = () => controller.abort(signal?.reason);
|
|
42008
|
+
signal?.throwIfAborted();
|
|
42009
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
42010
|
+
const timeout = setTimeout(
|
|
42011
|
+
() => controller.abort(new Error("Media import exceeded its time limit.")),
|
|
42012
|
+
options.timeoutMs ?? 30 * 6e4
|
|
42013
|
+
);
|
|
42014
|
+
timeout.unref();
|
|
42015
|
+
let idle;
|
|
42016
|
+
const touch = () => {
|
|
42017
|
+
clearTimeout(idle);
|
|
42018
|
+
idle = setTimeout(
|
|
42019
|
+
() => controller.abort(new Error("Media import stalled while waiting for data.")),
|
|
42020
|
+
options.idleMs ?? 6e4
|
|
42021
|
+
);
|
|
42022
|
+
idle.unref();
|
|
42023
|
+
};
|
|
42024
|
+
const fetcher = options.fetch ?? fetch;
|
|
42025
|
+
let source;
|
|
42026
|
+
let reader;
|
|
42027
|
+
const cancelRead = () => {
|
|
42028
|
+
void reader?.cancel(controller.signal.reason).catch(() => void 0);
|
|
42029
|
+
};
|
|
42030
|
+
let bytes = 0;
|
|
42031
|
+
try {
|
|
42032
|
+
touch();
|
|
42033
|
+
source = await download(fetcher, parsed, controller.signal);
|
|
42034
|
+
if (!source.ok) throw new Error(`Download failed (${source.status}).`);
|
|
42035
|
+
if (!source.body) throw new Error("Download returned no media body.");
|
|
42036
|
+
reader = source.body.getReader();
|
|
42037
|
+
const sourceReader = reader;
|
|
42038
|
+
controller.signal.addEventListener("abort", cancelRead, { once: true });
|
|
42039
|
+
const body = new ReadableStream({
|
|
42040
|
+
async pull(stream) {
|
|
42041
|
+
try {
|
|
42042
|
+
const { value, done } = await sourceReader.read();
|
|
42043
|
+
controller.signal.throwIfAborted();
|
|
42044
|
+
if (done) return stream.close();
|
|
42045
|
+
bytes += value.byteLength;
|
|
42046
|
+
touch();
|
|
42047
|
+
stream.enqueue(value);
|
|
42048
|
+
} catch (error51) {
|
|
42049
|
+
stream.error(error51);
|
|
42050
|
+
}
|
|
42051
|
+
},
|
|
42052
|
+
cancel(reason) {
|
|
42053
|
+
return sourceReader.cancel(reason);
|
|
42054
|
+
}
|
|
42055
|
+
});
|
|
42056
|
+
const response = await fetcher(endpoint, {
|
|
42057
|
+
method: "POST",
|
|
42058
|
+
body,
|
|
42059
|
+
duplex: "half",
|
|
42060
|
+
signal: controller.signal
|
|
42061
|
+
});
|
|
42062
|
+
const result = await uploadResult(response);
|
|
42063
|
+
if (typeof result.src !== "string" || !result.src.startsWith("./media/") || result.src.slice("./media/".length).split("/").some((part) => !part || part === "." || part === ".." || /[\\\0]/.test(part)) || !Number.isSafeInteger(result.byteSize) || result.byteSize !== bytes)
|
|
42064
|
+
throw new Error("Media upload returned an invalid file result.");
|
|
42065
|
+
return { src: result.src, bytes };
|
|
42066
|
+
} catch (error51) {
|
|
42067
|
+
if (controller.signal.aborted) throw controller.signal.reason;
|
|
42068
|
+
throw error51;
|
|
42069
|
+
} finally {
|
|
42070
|
+
clearTimeout(timeout);
|
|
42071
|
+
clearTimeout(idle);
|
|
42072
|
+
signal?.removeEventListener("abort", abort);
|
|
42073
|
+
controller.abort();
|
|
42074
|
+
controller.signal.removeEventListener("abort", cancelRead);
|
|
42075
|
+
await reader?.cancel().catch(() => void 0);
|
|
42076
|
+
reader?.releaseLock();
|
|
42077
|
+
if (source?.body && !source.body.locked) await source.body.cancel().catch(() => void 0);
|
|
42078
|
+
}
|
|
42079
|
+
}
|
|
42080
|
+
|
|
41938
42081
|
// src/tools/video-editor-local/standalone-resource.ts
|
|
41939
42082
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
41940
42083
|
import { join as join5 } from "node:path";
|
|
@@ -42032,7 +42175,7 @@ var restyleStyleSchema = external_exports.object({
|
|
|
42032
42175
|
});
|
|
42033
42176
|
|
|
42034
42177
|
// src/tools/video-editor-local/standalone-resource.ts
|
|
42035
|
-
var packageVersion = "1.0.
|
|
42178
|
+
var packageVersion = "1.0.4";
|
|
42036
42179
|
var VIDEO_EDITOR_RESOURCE_URI = packageVersion ? `ui://higgsfield/video-editor-v3-${encodeURIComponent(packageVersion)}.html` : "ui://higgsfield/video-editor-v3.html";
|
|
42037
42180
|
function panelHtmlPath(env = process.env) {
|
|
42038
42181
|
return env.VIDEO_EDITOR_LOCAL_HTML?.trim() || join5(import.meta.dirname, "index.html");
|
|
@@ -42079,7 +42222,7 @@ function registerPanelResource(server, html2, hosted2 = null) {
|
|
|
42079
42222
|
|
|
42080
42223
|
// src/tools/video-editor-local/relay.ts
|
|
42081
42224
|
import { openAsBlob } from "node:fs";
|
|
42082
|
-
import {
|
|
42225
|
+
import { mkdtemp, rm as rm3, writeFile as writeFile4 } from "node:fs/promises";
|
|
42083
42226
|
import { tmpdir } from "node:os";
|
|
42084
42227
|
import { join as join6 } from "node:path";
|
|
42085
42228
|
var MAX_CHUNK = 2 << 20;
|
|
@@ -42098,8 +42241,17 @@ async function httpTool(origin, call) {
|
|
|
42098
42241
|
function checkPath(path2) {
|
|
42099
42242
|
if (!path2.startsWith("/") || path2.startsWith("//")) throw new Error(`bad path ${path2}`);
|
|
42100
42243
|
}
|
|
42101
|
-
async function send(origin, method, path2, headers, body) {
|
|
42102
|
-
const res = await fetch(`${origin}${path2}`, {
|
|
42244
|
+
async function send(origin, method, path2, headers, body, signal) {
|
|
42245
|
+
const res = await fetch(`${origin}${path2}`, {
|
|
42246
|
+
method,
|
|
42247
|
+
headers,
|
|
42248
|
+
signal,
|
|
42249
|
+
...body ? { body } : {}
|
|
42250
|
+
});
|
|
42251
|
+
if (res.status === 404 && path2.startsWith(`/${STREAMING_MEDIA_PATH}?`)) {
|
|
42252
|
+
await res.body?.cancel();
|
|
42253
|
+
throw new Error(STREAMING_IMPORT_REQUIRED);
|
|
42254
|
+
}
|
|
42103
42255
|
const bytes = Buffer.from(await res.arrayBuffer());
|
|
42104
42256
|
if (bytes.length > MAX_CHUNK && res.status !== 206)
|
|
42105
42257
|
throw new Error(`${path2}: ${bytes.length} bytes without a range; ask for a range`);
|
|
@@ -42110,49 +42262,110 @@ async function send(origin, method, path2, headers, body) {
|
|
|
42110
42262
|
}
|
|
42111
42263
|
return { status: res.status, headers: kept, body: bytes.toString("base64") };
|
|
42112
42264
|
}
|
|
42113
|
-
|
|
42265
|
+
function uploadLimit(value, env, fallback) {
|
|
42266
|
+
const limit = value ?? Number(process.env[env] ?? fallback);
|
|
42267
|
+
if (!Number.isSafeInteger(limit) || limit <= 0)
|
|
42268
|
+
throw new Error(`${env} must be a positive integer`);
|
|
42269
|
+
return limit;
|
|
42270
|
+
}
|
|
42114
42271
|
var UploadParts = class {
|
|
42115
42272
|
open = /* @__PURE__ */ new Map();
|
|
42116
|
-
|
|
42117
|
-
|
|
42118
|
-
|
|
42273
|
+
maxBytes;
|
|
42274
|
+
maxConcurrent;
|
|
42275
|
+
idleMs;
|
|
42276
|
+
totalMs;
|
|
42277
|
+
constructor(limits = {}) {
|
|
42278
|
+
this.maxBytes = uploadLimit(limits.maxBytes, "HIGGSEDIT_MEDIA_MAX_BYTES", 8 * 1024 ** 3);
|
|
42279
|
+
this.maxConcurrent = uploadLimit(limits.maxConcurrent, "HIGGSEDIT_MEDIA_MAX_CONCURRENT", 4);
|
|
42280
|
+
this.idleMs = uploadLimit(limits.idleMs, "HIGGSEDIT_MEDIA_IDLE_MS", 6e4);
|
|
42281
|
+
this.totalMs = uploadLimit(limits.totalMs, "HIGGSEDIT_MEDIA_TOTAL_MS", 30 * 6e4);
|
|
42282
|
+
}
|
|
42283
|
+
async add(origin, part, signal) {
|
|
42284
|
+
if (!/^[\w-]{8,64}$/.test(part.id)) throw new Error("Invalid upload id");
|
|
42285
|
+
checkPath(part.path);
|
|
42119
42286
|
let upload = this.open.get(part.id);
|
|
42287
|
+
if (upload && (upload.origin !== origin || upload.path !== part.path))
|
|
42288
|
+
throw new Error("Upload belongs to another project or path");
|
|
42289
|
+
if (part.cancel) {
|
|
42290
|
+
if (upload) await this.drop(part.id, upload);
|
|
42291
|
+
return { cancelled: true };
|
|
42292
|
+
}
|
|
42293
|
+
signal?.throwIfAborted();
|
|
42294
|
+
if (upload?.busy)
|
|
42295
|
+
throw new Error("Upload part is already being written; wait before sending the next part");
|
|
42120
42296
|
if (!upload) {
|
|
42121
42297
|
if (part.offset !== 0) throw new Error(`upload ${part.id} is unknown; start at offset 0`);
|
|
42122
|
-
|
|
42123
|
-
|
|
42124
|
-
|
|
42125
|
-
|
|
42298
|
+
if (this.open.size >= this.maxConcurrent)
|
|
42299
|
+
throw new Error("Too many active media uploads; wait for one to finish");
|
|
42300
|
+
const expire = () => {
|
|
42301
|
+
void this.drop(part.id, created).catch(() => void 0);
|
|
42302
|
+
};
|
|
42303
|
+
const created = {
|
|
42304
|
+
origin,
|
|
42126
42305
|
path: part.path,
|
|
42127
42306
|
size: 0,
|
|
42128
|
-
|
|
42307
|
+
busy: false,
|
|
42308
|
+
abort: new AbortController(),
|
|
42309
|
+
idle: setTimeout(expire, this.idleMs),
|
|
42310
|
+
total: setTimeout(expire, this.totalMs)
|
|
42129
42311
|
};
|
|
42312
|
+
created.idle.unref();
|
|
42313
|
+
created.total.unref();
|
|
42314
|
+
upload = created;
|
|
42130
42315
|
this.open.set(part.id, upload);
|
|
42131
42316
|
}
|
|
42132
|
-
|
|
42133
|
-
|
|
42134
|
-
|
|
42135
|
-
|
|
42136
|
-
|
|
42137
|
-
await appendFile(upload.file, bytes);
|
|
42138
|
-
upload.size += bytes.length;
|
|
42139
|
-
upload.touched = Date.now();
|
|
42140
|
-
if (!part.last) return { received: upload.size };
|
|
42141
|
-
this.open.delete(part.id);
|
|
42317
|
+
const current = upload;
|
|
42318
|
+
current.busy = true;
|
|
42319
|
+
let complete = false;
|
|
42320
|
+
const cancel = () => current.abort.abort(signal?.reason);
|
|
42321
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
42142
42322
|
try {
|
|
42143
|
-
|
|
42323
|
+
if (part.offset !== current.size)
|
|
42324
|
+
throw new Error(`upload ${part.id}: expected byte ${current.size}`);
|
|
42325
|
+
if (part.part.length > Math.ceil(MAX_CHUNK / 3) * 4)
|
|
42326
|
+
throw new Error("Upload part exceeds 2 MiB");
|
|
42327
|
+
const bytes = Buffer.from(part.part, "base64");
|
|
42328
|
+
if (bytes.toString("base64") !== part.part)
|
|
42329
|
+
throw new Error("Upload part is not valid base64");
|
|
42330
|
+
if (bytes.length > MAX_CHUNK) throw new Error("Upload part exceeds 2 MiB");
|
|
42331
|
+
if (current.size + bytes.length > this.maxBytes)
|
|
42332
|
+
throw new Error(`Upload exceeds ${this.maxBytes} bytes`);
|
|
42333
|
+
current.abort.signal.throwIfAborted();
|
|
42334
|
+
current.directory ??= await mkdtemp(join6(tmpdir(), "video-editor-upload-"));
|
|
42335
|
+
current.abort.signal.throwIfAborted();
|
|
42336
|
+
const file2 = join6(current.directory, "body");
|
|
42337
|
+
await writeFile4(file2, bytes, { flag: "a", mode: 384, signal: current.abort.signal });
|
|
42338
|
+
current.size += bytes.length;
|
|
42339
|
+
current.idle.refresh();
|
|
42340
|
+
if (!part.last) {
|
|
42341
|
+
complete = true;
|
|
42342
|
+
return { received: current.size };
|
|
42343
|
+
}
|
|
42344
|
+
const endpoint = new URL(current.path, origin);
|
|
42345
|
+
if (endpoint.pathname === "/api/media") endpoint.pathname = `/${STREAMING_MEDIA_PATH}`;
|
|
42346
|
+
const result = await send(
|
|
42347
|
+
origin,
|
|
42348
|
+
"POST",
|
|
42349
|
+
endpoint.pathname + endpoint.search,
|
|
42350
|
+
new Headers(),
|
|
42351
|
+
await openAsBlob(file2),
|
|
42352
|
+
current.abort.signal
|
|
42353
|
+
);
|
|
42354
|
+
complete = true;
|
|
42355
|
+
return result;
|
|
42144
42356
|
} finally {
|
|
42145
|
-
|
|
42357
|
+
signal?.removeEventListener("abort", cancel);
|
|
42358
|
+
current.busy = false;
|
|
42359
|
+
if (!complete || part.last || current.abort.signal.aborted) await this.drop(part.id, current);
|
|
42146
42360
|
}
|
|
42147
42361
|
}
|
|
42148
|
-
drop(id2) {
|
|
42149
|
-
|
|
42150
|
-
|
|
42151
|
-
|
|
42152
|
-
|
|
42153
|
-
|
|
42154
|
-
|
|
42155
|
-
for (const [id2, upload] of this.open) if (upload.touched < cutoff) this.drop(id2);
|
|
42362
|
+
async drop(id2, upload) {
|
|
42363
|
+
upload.abort.abort(new Error("Media upload cancelled or expired"));
|
|
42364
|
+
clearTimeout(upload.idle);
|
|
42365
|
+
clearTimeout(upload.total);
|
|
42366
|
+
if (upload.busy) return;
|
|
42367
|
+
if (this.open.get(id2) === upload) this.open.delete(id2);
|
|
42368
|
+
if (upload.directory) await rm3(upload.directory, { recursive: true, force: true });
|
|
42156
42369
|
}
|
|
42157
42370
|
};
|
|
42158
42371
|
var reload = (undo) => ({
|
|
@@ -42316,11 +42529,71 @@ import {
|
|
|
42316
42529
|
rm as rm4,
|
|
42317
42530
|
stat as stat2,
|
|
42318
42531
|
utimes,
|
|
42319
|
-
writeFile as
|
|
42532
|
+
writeFile as writeFile5
|
|
42320
42533
|
} from "node:fs/promises";
|
|
42321
42534
|
import { createServer as createServer3 } from "node:net";
|
|
42322
42535
|
import { homedir as homedir3 } from "node:os";
|
|
42323
42536
|
import { join as join8 } from "node:path";
|
|
42537
|
+
|
|
42538
|
+
// src/tools/video-editor-local/session-health.ts
|
|
42539
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
42540
|
+
var PROBE_MS = 2e3;
|
|
42541
|
+
async function request2(origin, path2, timeoutMs, read, method = "GET") {
|
|
42542
|
+
const controller = new AbortController();
|
|
42543
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
42544
|
+
timer.unref();
|
|
42545
|
+
try {
|
|
42546
|
+
const response = await fetch(new URL(path2, origin), { method, signal: controller.signal });
|
|
42547
|
+
return response.ok ? await read(response) : void 0;
|
|
42548
|
+
} catch {
|
|
42549
|
+
return void 0;
|
|
42550
|
+
} finally {
|
|
42551
|
+
controller.abort();
|
|
42552
|
+
clearTimeout(timer);
|
|
42553
|
+
}
|
|
42554
|
+
}
|
|
42555
|
+
async function waitForDevReady(origin, exited, timeoutMs) {
|
|
42556
|
+
const deadline = Date.now() + timeoutMs;
|
|
42557
|
+
let backoff = 50;
|
|
42558
|
+
while (!exited()) {
|
|
42559
|
+
const remaining = deadline - Date.now();
|
|
42560
|
+
if (remaining <= 0) return false;
|
|
42561
|
+
if (await request2(origin, "/api/history", Math.min(PROBE_MS, remaining), async () => true))
|
|
42562
|
+
return !exited();
|
|
42563
|
+
if (exited()) return false;
|
|
42564
|
+
const budget = deadline - Date.now();
|
|
42565
|
+
if (budget <= 0) return false;
|
|
42566
|
+
await delay(Math.min(backoff, budget));
|
|
42567
|
+
if (budget <= backoff) return false;
|
|
42568
|
+
backoff = Math.min(backoff * 2, 1e3);
|
|
42569
|
+
}
|
|
42570
|
+
return false;
|
|
42571
|
+
}
|
|
42572
|
+
async function requestIdleStop(origin) {
|
|
42573
|
+
return await request2(
|
|
42574
|
+
origin,
|
|
42575
|
+
"/api/idle-stop",
|
|
42576
|
+
1e3,
|
|
42577
|
+
async (response) => {
|
|
42578
|
+
const reader = response.body?.getReader();
|
|
42579
|
+
if (!reader) return false;
|
|
42580
|
+
const chunks = [];
|
|
42581
|
+
let bytes = 0;
|
|
42582
|
+
for (; ; ) {
|
|
42583
|
+
const next = await reader.read();
|
|
42584
|
+
if (next.done) break;
|
|
42585
|
+
bytes += next.value.byteLength;
|
|
42586
|
+
if (bytes > 1024) return false;
|
|
42587
|
+
chunks.push(next.value);
|
|
42588
|
+
}
|
|
42589
|
+
const value = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
42590
|
+
return typeof value === "object" && value !== null && "stopping" in value && value.stopping === true;
|
|
42591
|
+
},
|
|
42592
|
+
"POST"
|
|
42593
|
+
) === true;
|
|
42594
|
+
}
|
|
42595
|
+
|
|
42596
|
+
// src/tools/video-editor-local/session.ts
|
|
42324
42597
|
function localStateDirectory(env = process.env) {
|
|
42325
42598
|
return env.VIDEO_EDITOR_LOCAL_STATE?.trim() || join8(homedir3(), ".higgsfield", "video-editor-local");
|
|
42326
42599
|
}
|
|
@@ -42328,18 +42601,14 @@ var IDLE_MS = 60 * 60 * 1e3;
|
|
|
42328
42601
|
var sessionIdOf = (root) => createHash4("sha256").update(root).digest("hex").slice(0, 16);
|
|
42329
42602
|
var SESSION_ID = /^[0-9a-f]{16}$/;
|
|
42330
42603
|
var alive = (pid) => {
|
|
42331
|
-
if (!pid) return false;
|
|
42604
|
+
if (!Number.isSafeInteger(pid) || !pid || pid < 1) return false;
|
|
42332
42605
|
try {
|
|
42333
42606
|
process.kill(pid, 0);
|
|
42334
42607
|
return true;
|
|
42335
|
-
} catch {
|
|
42336
|
-
return
|
|
42608
|
+
} catch (error51) {
|
|
42609
|
+
return error51.code !== "ESRCH";
|
|
42337
42610
|
}
|
|
42338
42611
|
};
|
|
42339
|
-
var answers = (origin) => fetch(`${origin}/api/history`, { signal: AbortSignal.timeout(1e3) }).then(
|
|
42340
|
-
(r) => r.ok,
|
|
42341
|
-
() => false
|
|
42342
|
-
);
|
|
42343
42612
|
var sleep2 = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
42344
42613
|
var freePort = () => new Promise((resolve3, reject) => {
|
|
42345
42614
|
const server = createServer3();
|
|
@@ -42364,18 +42633,24 @@ async function startDev(root) {
|
|
|
42364
42633
|
});
|
|
42365
42634
|
child.unref();
|
|
42366
42635
|
const origin = `http://127.0.0.1:${port}`;
|
|
42367
|
-
|
|
42368
|
-
|
|
42369
|
-
|
|
42370
|
-
|
|
42371
|
-
|
|
42636
|
+
let failed = false;
|
|
42637
|
+
const onError = () => {
|
|
42638
|
+
failed = true;
|
|
42639
|
+
};
|
|
42640
|
+
child.once("error", onError);
|
|
42641
|
+
try {
|
|
42642
|
+
if (await waitForDevReady(
|
|
42643
|
+
origin,
|
|
42644
|
+
() => failed || child.exitCode !== null || child.signalCode !== null,
|
|
42645
|
+
READY_MS
|
|
42646
|
+
))
|
|
42647
|
+
return { origin, pid: child.pid ?? 0 };
|
|
42648
|
+
} finally {
|
|
42649
|
+
child.removeListener("error", onError);
|
|
42372
42650
|
}
|
|
42373
42651
|
child.kill();
|
|
42374
42652
|
throw new Error(`higgsedit dev did not start for ${root}; run \`higgsedit doctor\``);
|
|
42375
42653
|
}
|
|
42376
|
-
var stopPid = (pid) => {
|
|
42377
|
-
if (pid && pid !== process.pid && alive(pid)) process.kill(pid);
|
|
42378
|
-
};
|
|
42379
42654
|
var parseRecord = (text) => {
|
|
42380
42655
|
try {
|
|
42381
42656
|
const record2 = JSON.parse(text);
|
|
@@ -42397,14 +42672,14 @@ function createSessionStore(options = {}) {
|
|
|
42397
42672
|
const write = async (id2, record2) => {
|
|
42398
42673
|
await mkdir4(projects, { recursive: true, mode: 448 });
|
|
42399
42674
|
const temp = `${file2(id2, "json")}.${randomUUID4()}.tmp`;
|
|
42400
|
-
await
|
|
42675
|
+
await writeFile5(temp, JSON.stringify(record2), { mode: 384 });
|
|
42401
42676
|
await rename3(temp, file2(id2, "json"));
|
|
42402
42677
|
};
|
|
42403
42678
|
const create = async (record2) => {
|
|
42404
42679
|
await mkdir4(projects, { recursive: true, mode: 448 });
|
|
42405
42680
|
const target = file2(sessionIdOf(record2.root), "json");
|
|
42406
42681
|
const temp = `${target}.${randomUUID4()}.tmp`;
|
|
42407
|
-
await
|
|
42682
|
+
await writeFile5(temp, JSON.stringify(record2), { mode: 384 });
|
|
42408
42683
|
await link2(temp, target).catch((error51) => {
|
|
42409
42684
|
if (error51.code !== "EEXIST") throw error51;
|
|
42410
42685
|
});
|
|
@@ -42446,7 +42721,7 @@ function createSessionStore(options = {}) {
|
|
|
42446
42721
|
for (; ; ) {
|
|
42447
42722
|
const body = JSON.stringify({ pid: process.pid, at: Date.now() });
|
|
42448
42723
|
try {
|
|
42449
|
-
await
|
|
42724
|
+
await writeFile5(lock, body, { flag: "wx", mode: 384 });
|
|
42450
42725
|
break;
|
|
42451
42726
|
} catch (error51) {
|
|
42452
42727
|
if (error51.code !== "EEXIST") throw error51;
|
|
@@ -42480,72 +42755,114 @@ function createSessionStore(options = {}) {
|
|
|
42480
42755
|
const used = file2(id2, "used");
|
|
42481
42756
|
const time3 = new Date(at);
|
|
42482
42757
|
await utimes(used, time3, time3).catch(async () => {
|
|
42483
|
-
await
|
|
42758
|
+
await writeFile5(used, "", { mode: 384 });
|
|
42484
42759
|
await utimes(used, time3, time3);
|
|
42485
42760
|
});
|
|
42486
42761
|
};
|
|
42487
|
-
const usedAt = async (record2) =>
|
|
42762
|
+
const usedAt = async (record2) => {
|
|
42763
|
+
const id2 = sessionIdOf(record2.root);
|
|
42764
|
+
const written = (await stat2(file2(id2, "used")).catch(() => null))?.mtimeMs ?? record2.openedAt;
|
|
42765
|
+
return Math.max(written, touched.get(id2) ?? -Infinity);
|
|
42766
|
+
};
|
|
42767
|
+
const activityDirectory = (id2) => join8(projects, `${id2}.activity`);
|
|
42768
|
+
const hasActivity = async (id2) => {
|
|
42769
|
+
const names = await readdir2(activityDirectory(id2)).catch((error51) => {
|
|
42770
|
+
if (error51.code === "ENOENT") return [];
|
|
42771
|
+
throw error51;
|
|
42772
|
+
});
|
|
42773
|
+
for (const name of names) {
|
|
42774
|
+
const owner = /^([1-9]\d*)-[0-9a-f-]{36}$/.exec(name);
|
|
42775
|
+
if (!owner || alive(Number(owner[1]))) return true;
|
|
42776
|
+
await rm4(join8(activityDirectory(id2), name), { force: true });
|
|
42777
|
+
}
|
|
42778
|
+
return false;
|
|
42779
|
+
};
|
|
42780
|
+
const recentRecords = async () => {
|
|
42781
|
+
const all = await records();
|
|
42782
|
+
const live = await Promise.all(all.map((record2) => hasProjectFile(record2.root)));
|
|
42783
|
+
return all.filter((_, i) => live[i]).slice(0, RECENT);
|
|
42784
|
+
};
|
|
42488
42785
|
const session = async (root, origin) => ({
|
|
42489
42786
|
root,
|
|
42490
42787
|
id: sessionIdOf(root),
|
|
42491
42788
|
name: await projectName(directory, root),
|
|
42492
42789
|
origin
|
|
42493
42790
|
});
|
|
42494
|
-
const
|
|
42495
|
-
const stopIdle = async (
|
|
42791
|
+
const running = (record2) => Boolean(record2?.origin && alive(record2.pid));
|
|
42792
|
+
const stopIdle = async () => {
|
|
42496
42793
|
const live = (await records()).filter((record2) => record2.origin && alive(record2.pid));
|
|
42497
42794
|
const cutoff = now() - idleMs;
|
|
42498
|
-
const idle = (await Promise.all(
|
|
42499
|
-
live.filter((record2) => sessionIdOf(record2.root) !== keep).map(async (record2) => ({ record: record2, used: await usedAt(record2) }))
|
|
42500
|
-
)).filter(({ used }) => used < cutoff);
|
|
42795
|
+
const idle = (await Promise.all(live.map(async (record2) => ({ record: record2, used: await usedAt(record2) })))).filter(({ used }) => used < cutoff);
|
|
42501
42796
|
for (const { record: record2 } of idle) {
|
|
42502
42797
|
const id2 = sessionIdOf(record2.root);
|
|
42503
42798
|
await locked(id2, async () => {
|
|
42504
42799
|
const saved = await read(id2);
|
|
42505
|
-
if (!saved?.origin || await usedAt(saved) >= cutoff) return;
|
|
42506
|
-
|
|
42800
|
+
if (!saved?.origin || await usedAt(saved) >= cutoff || await hasActivity(id2)) return;
|
|
42801
|
+
if (!await requestIdleStop(saved.origin)) return;
|
|
42507
42802
|
await write(id2, { root: saved.root, openedAt: saved.openedAt });
|
|
42803
|
+
touched.delete(id2);
|
|
42508
42804
|
});
|
|
42509
42805
|
}
|
|
42510
42806
|
};
|
|
42807
|
+
let sweeping;
|
|
42808
|
+
const sweep = () => {
|
|
42809
|
+
if (sweeping) return sweeping;
|
|
42810
|
+
const pending = stopIdle();
|
|
42811
|
+
sweeping = pending;
|
|
42812
|
+
const done = () => {
|
|
42813
|
+
if (sweeping === pending) sweeping = void 0;
|
|
42814
|
+
};
|
|
42815
|
+
void pending.then(done, done);
|
|
42816
|
+
return pending;
|
|
42817
|
+
};
|
|
42511
42818
|
const chains = /* @__PURE__ */ new Map();
|
|
42512
42819
|
const serialized = (id2, run) => {
|
|
42513
42820
|
const next = (chains.get(id2) ?? Promise.resolve()).then(run, run);
|
|
42514
|
-
|
|
42515
|
-
|
|
42516
|
-
|
|
42517
|
-
})
|
|
42821
|
+
const settled = next.then(
|
|
42822
|
+
() => void 0,
|
|
42823
|
+
() => void 0
|
|
42518
42824
|
);
|
|
42825
|
+
chains.set(id2, settled);
|
|
42826
|
+
void settled.then(() => {
|
|
42827
|
+
if (chains.get(id2) === settled) chains.delete(id2);
|
|
42828
|
+
});
|
|
42519
42829
|
return next;
|
|
42520
42830
|
};
|
|
42831
|
+
const reading = /* @__PURE__ */ new Map();
|
|
42521
42832
|
const ensure = (root, opened) => {
|
|
42522
42833
|
const id2 = sessionIdOf(root);
|
|
42523
|
-
|
|
42524
|
-
|
|
42834
|
+
const pending = !opened && reading.get(id2);
|
|
42835
|
+
if (pending) return pending;
|
|
42836
|
+
const work = serialized(id2, async () => {
|
|
42525
42837
|
let saved = await read(id2);
|
|
42526
|
-
|
|
42527
|
-
if (opened || !await healthy(saved, cli))
|
|
42838
|
+
if (opened || !running(saved))
|
|
42528
42839
|
saved = await locked(id2, async () => {
|
|
42529
42840
|
const current = await read(id2);
|
|
42530
42841
|
const openedAt = opened ? now() : current?.openedAt ?? now();
|
|
42531
42842
|
let record2;
|
|
42532
|
-
if (
|
|
42843
|
+
if (running(current)) {
|
|
42533
42844
|
record2 = { ...current, openedAt };
|
|
42534
42845
|
if (opened) await write(id2, record2);
|
|
42535
42846
|
} else {
|
|
42536
|
-
|
|
42847
|
+
const cli = currentCli();
|
|
42537
42848
|
if (opened) await write(id2, { root, openedAt });
|
|
42538
42849
|
record2 = { root, ...await start(root), cli, openedAt };
|
|
42539
42850
|
await write(id2, record2);
|
|
42540
|
-
started = true;
|
|
42541
42851
|
}
|
|
42542
42852
|
await touch(id2, true);
|
|
42543
42853
|
return record2;
|
|
42544
42854
|
});
|
|
42545
42855
|
else await touch(id2);
|
|
42546
|
-
if (started) await stopIdle(id2);
|
|
42547
42856
|
return session(root, saved.origin);
|
|
42548
42857
|
});
|
|
42858
|
+
if (!opened) {
|
|
42859
|
+
reading.set(id2, work);
|
|
42860
|
+
const done = () => {
|
|
42861
|
+
if (reading.get(id2) === work) reading.delete(id2);
|
|
42862
|
+
};
|
|
42863
|
+
void work.then(done, done);
|
|
42864
|
+
}
|
|
42865
|
+
return work;
|
|
42549
42866
|
};
|
|
42550
42867
|
const locate = async (ref) => {
|
|
42551
42868
|
if (ref && SESSION_ID.test(ref)) {
|
|
@@ -42563,17 +42880,41 @@ function createSessionStore(options = {}) {
|
|
|
42563
42880
|
const store = {
|
|
42564
42881
|
roots,
|
|
42565
42882
|
/** Stops dev servers unused for an hour; the MCP server runs this on a timer. */
|
|
42566
|
-
stopIdle:
|
|
42883
|
+
stopIdle: sweep,
|
|
42567
42884
|
/** A project's dev server origin as last written, without a health check: the direct route reads it per request. */
|
|
42568
42885
|
peek(id2) {
|
|
42569
42886
|
if (!SESSION_ID.test(id2)) return null;
|
|
42570
42887
|
try {
|
|
42571
42888
|
const saved = parseRecord(readFileSync2(file2(id2, "json"), "utf8"));
|
|
42572
|
-
|
|
42889
|
+
if (!running(saved)) return null;
|
|
42890
|
+
void touch(id2).catch(() => void 0);
|
|
42891
|
+
return { origin: saved.origin };
|
|
42573
42892
|
} catch {
|
|
42574
42893
|
return null;
|
|
42575
42894
|
}
|
|
42576
42895
|
},
|
|
42896
|
+
/** Pins an operation across MCP processes without heartbeat timers; crashes release on the next sweep. */
|
|
42897
|
+
async withActivity(current, run) {
|
|
42898
|
+
const lease = await locked(current.id, async () => {
|
|
42899
|
+
const saved = await read(current.id);
|
|
42900
|
+
if (!running(saved) || saved.origin !== current.origin)
|
|
42901
|
+
throw new Error(
|
|
42902
|
+
"The local project server changed before this operation. Retry the operation."
|
|
42903
|
+
);
|
|
42904
|
+
const directory2 = activityDirectory(current.id);
|
|
42905
|
+
await mkdir4(directory2, { recursive: true, mode: 448 });
|
|
42906
|
+
const path2 = join8(directory2, `${process.pid}-${randomUUID4()}`);
|
|
42907
|
+
await writeFile5(path2, "", { flag: "wx", mode: 384 });
|
|
42908
|
+
return path2;
|
|
42909
|
+
});
|
|
42910
|
+
try {
|
|
42911
|
+
await touch(current.id, true);
|
|
42912
|
+
return await run();
|
|
42913
|
+
} finally {
|
|
42914
|
+
await rm4(lease, { force: true });
|
|
42915
|
+
await touch(current.id, true);
|
|
42916
|
+
}
|
|
42917
|
+
},
|
|
42577
42918
|
async open(path2) {
|
|
42578
42919
|
const root = await resolveProjectDir(path2, roots());
|
|
42579
42920
|
await migrated();
|
|
@@ -42603,9 +42944,16 @@ function createSessionStore(options = {}) {
|
|
|
42603
42944
|
},
|
|
42604
42945
|
/** Recently opened folders that still hold a project, newest first. */
|
|
42605
42946
|
async recent() {
|
|
42606
|
-
|
|
42607
|
-
|
|
42608
|
-
|
|
42947
|
+
return (await recentRecords()).map((record2) => record2.root);
|
|
42948
|
+
},
|
|
42949
|
+
/** `recent()` with each folder's last activity: its dev server's last use, else its last open. */
|
|
42950
|
+
async recentActivity() {
|
|
42951
|
+
return Promise.all(
|
|
42952
|
+
(await recentRecords()).map(async (record2) => ({
|
|
42953
|
+
root: record2.root,
|
|
42954
|
+
usedAt: await usedAt(record2)
|
|
42955
|
+
}))
|
|
42956
|
+
);
|
|
42609
42957
|
},
|
|
42610
42958
|
/** Projects whose dev server is running, newest opened first; no health check. */
|
|
42611
42959
|
async live() {
|
|
@@ -42794,11 +43142,14 @@ function registerVideoEditorLocalTools(server, options = {}) {
|
|
|
42794
43142
|
};
|
|
42795
43143
|
const scoped = (project, run) => guarded(async () => {
|
|
42796
43144
|
const session = await store.session(project);
|
|
42797
|
-
return withProject(
|
|
43145
|
+
return withProject(
|
|
43146
|
+
await store.withActivity(session, () => run(session)),
|
|
43147
|
+
await naming(session, project)
|
|
43148
|
+
);
|
|
42798
43149
|
});
|
|
42799
43150
|
const mediaScoped = (project, run) => guarded(async () => {
|
|
42800
43151
|
const session = project ? await store.session(project) : await store.find().catch(() => null);
|
|
42801
|
-
const result = await run(session
|
|
43152
|
+
const result = session ? await store.withActivity(session, () => run(session.root)) : await run(void 0);
|
|
42802
43153
|
return session ? withProject(result, await naming(session, project)) : result;
|
|
42803
43154
|
});
|
|
42804
43155
|
const opened = async (dir) => {
|
|
@@ -43001,19 +43352,7 @@ ${LOCAL_PROJECT_GUIDE}`);
|
|
|
43001
43352
|
}),
|
|
43002
43353
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
|
|
43003
43354
|
},
|
|
43004
|
-
async ({ url: url2, file_name, project }) => scoped(project, async ({
|
|
43005
|
-
const parsed = new URL(url2);
|
|
43006
|
-
if (parsed.protocol !== "https:") throw new Error("Only https URLs can be imported.");
|
|
43007
|
-
const response = await fetch(parsed);
|
|
43008
|
-
if (!response.ok)
|
|
43009
|
-
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
43010
|
-
const bytes = Buffer.from(await response.arrayBuffer());
|
|
43011
|
-
const name = (file_name ?? decodeURIComponent(parsed.pathname.split("/").at(-1) ?? "")).replace(/[/\\]/g, "_").replace(/^\.+/, "") || "import";
|
|
43012
|
-
const dir = join9(root, "media");
|
|
43013
|
-
await mkdir5(dir, { recursive: true });
|
|
43014
|
-
const file2 = await newFile(dir, name, (path2) => writeFile5(path2, bytes, { flag: "wx" }));
|
|
43015
|
-
return { src: `./media/${file2}`, bytes: bytes.length };
|
|
43016
|
-
})
|
|
43355
|
+
async ({ url: url2, file_name, project }, ctx) => scoped(project, async ({ origin }) => importMedia(origin, url2, file_name, ctx.mcpReq.signal))
|
|
43017
43356
|
);
|
|
43018
43357
|
server.registerTool(
|
|
43019
43358
|
"video_editing_preview_frames",
|
|
@@ -43331,18 +43670,20 @@ function registerPanelRelay(server, store, stateDirectory, direct) {
|
|
|
43331
43670
|
server,
|
|
43332
43671
|
"video_editing_session",
|
|
43333
43672
|
{
|
|
43334
|
-
description: "Editor: a local project folder (the one `project` names, else the last opened) and the loopback base of the direct route, or why none is open; plus the allowed roots and recent project folders.",
|
|
43673
|
+
description: "Editor: a local project folder (the one `project` names, else the last opened) and the loopback base of the direct route, or why none is open; plus the allowed roots and recent project folders with their names and last activity.",
|
|
43335
43674
|
inputSchema: { project: sessionArg },
|
|
43336
43675
|
_meta: appOnly
|
|
43337
43676
|
},
|
|
43338
43677
|
async ({ project }) => {
|
|
43339
|
-
const
|
|
43678
|
+
const activity = await store.recentActivity();
|
|
43679
|
+
const recent = activity.map(({ root }) => root);
|
|
43340
43680
|
const names = Object.fromEntries(
|
|
43341
43681
|
await Promise.all(
|
|
43342
43682
|
recent.map(async (path2) => [path2, await projectName(stateDirectory, path2)])
|
|
43343
43683
|
)
|
|
43344
43684
|
);
|
|
43345
|
-
const
|
|
43685
|
+
const usedAt = Object.fromEntries(activity.map(({ root, usedAt: usedAt2 }) => [root, usedAt2]));
|
|
43686
|
+
const listed = { roots: store.roots(), recent, names, usedAt };
|
|
43346
43687
|
try {
|
|
43347
43688
|
const session = await store.find(project);
|
|
43348
43689
|
return reply(
|
|
@@ -43363,7 +43704,7 @@ function registerPanelRelay(server, store, stateDirectory, direct) {
|
|
|
43363
43704
|
_meta: appOnly
|
|
43364
43705
|
},
|
|
43365
43706
|
async ({ lines }) => guarded(async () => {
|
|
43366
|
-
await
|
|
43707
|
+
await appendFile(
|
|
43367
43708
|
join9(stateDirectory, "panel.log"),
|
|
43368
43709
|
lines.map((line) => `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
43369
43710
|
`).join("")
|
|
@@ -43399,13 +43740,17 @@ function registerPanelRelay(server, store, stateDirectory, direct) {
|
|
|
43399
43740
|
offset: external_exports.number().int().nonnegative(),
|
|
43400
43741
|
part: external_exports.string().max(4 << 20),
|
|
43401
43742
|
last: external_exports.boolean(),
|
|
43743
|
+
cancel: external_exports.boolean().optional(),
|
|
43402
43744
|
project: sessionArg
|
|
43403
43745
|
},
|
|
43404
43746
|
_meta: appOnly
|
|
43405
43747
|
},
|
|
43406
|
-
async ({ project, ...part }) => guarded(async () =>
|
|
43407
|
-
|
|
43408
|
-
|
|
43748
|
+
async ({ project, ...part }, ctx) => guarded(async () => {
|
|
43749
|
+
const session = await store.session(project);
|
|
43750
|
+
return store.withActivity(session, async () => ({
|
|
43751
|
+
...await uploads.add(session.origin, part, ctx.mcpReq.signal)
|
|
43752
|
+
}));
|
|
43753
|
+
})
|
|
43409
43754
|
);
|
|
43410
43755
|
registerAppTool(
|
|
43411
43756
|
server,
|
|
@@ -43461,7 +43806,7 @@ function registerPanelRelay(server, store, stateDirectory, direct) {
|
|
|
43461
43806
|
);
|
|
43462
43807
|
if (size !== offset) throw new Error(`file ${id2}: expected byte ${size}; start again`);
|
|
43463
43808
|
const bytes = Buffer.from(part, "base64");
|
|
43464
|
-
await
|
|
43809
|
+
await writeFile6(temp, bytes, { flag: offset === 0 ? "w" : "a" });
|
|
43465
43810
|
if (!last) return { received: offset + bytes.length };
|
|
43466
43811
|
const file2 = await newFile(dir, name, (path2) => link3(temp, path2));
|
|
43467
43812
|
await rm5(temp, { force: true });
|
|
@@ -43513,7 +43858,34 @@ var operation = external_exports.discriminatedUnion("op", [
|
|
|
43513
43858
|
})
|
|
43514
43859
|
]);
|
|
43515
43860
|
var timelineInputs = {
|
|
43516
|
-
video_editor_read_timeline: external_exports.object({
|
|
43861
|
+
video_editor_read_timeline: external_exports.object({
|
|
43862
|
+
request_id: id.optional(),
|
|
43863
|
+
view: external_exports.enum(["auto", "summary", "clips", "assets"]).optional(),
|
|
43864
|
+
scope: external_exports.enum(["scene", "selection"]).optional(),
|
|
43865
|
+
clip_ids: external_exports.array(id).min(1).max(200).optional(),
|
|
43866
|
+
time_range: external_exports.object({ start: external_exports.number().nonnegative(), end: external_exports.number().positive() }).optional(),
|
|
43867
|
+
offset: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
|
|
43868
|
+
limit: external_exports.number().int().min(1).max(100).optional(),
|
|
43869
|
+
expected_revision: id.optional(),
|
|
43870
|
+
text_offset: external_exports.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional()
|
|
43871
|
+
}).strict().refine((input) => !input.time_range || input.time_range.end > input.time_range.start, {
|
|
43872
|
+
message: "time_range.end must be after time_range.start (timeline seconds)."
|
|
43873
|
+
}).refine(
|
|
43874
|
+
(input) => !((input.offset ?? 0) > 0 || (input.text_offset ?? 0) > 0) || Boolean(input.request_id && input.expected_revision),
|
|
43875
|
+
{
|
|
43876
|
+
message: "Continuation requires the original request_id and expected_revision."
|
|
43877
|
+
}
|
|
43878
|
+
).refine(
|
|
43879
|
+
(input) => input.text_offset === void 0 || input.view === "clips" && input.clip_ids?.length === 1 && !input.offset,
|
|
43880
|
+
{
|
|
43881
|
+
message: "text_offset requires view=clips, exactly one clip_id, and offset=0."
|
|
43882
|
+
}
|
|
43883
|
+
).refine(
|
|
43884
|
+
(input) => input.view !== "assets" || input.scope === void 0 && input.clip_ids === void 0 && input.time_range === void 0,
|
|
43885
|
+
{
|
|
43886
|
+
message: "Asset pages do not accept clip scope, IDs or time filters."
|
|
43887
|
+
}
|
|
43888
|
+
),
|
|
43517
43889
|
video_editor_apply_timeline: external_exports.object({
|
|
43518
43890
|
request_id: id,
|
|
43519
43891
|
expected_revision: id,
|
|
@@ -43550,7 +43922,7 @@ var TIMELINE_CHANNEL_META = "higgsfield/timeline-channel";
|
|
|
43550
43922
|
|
|
43551
43923
|
// src/tools/video-editor-timeline/register.ts
|
|
43552
43924
|
var descriptions = {
|
|
43553
|
-
video_editor_read_timeline: "Read the live browser Video Editor timeline, captured selection, assets and revision. Use editor_session_id from the editor context attachment. Omit request_id only for a new task; retain
|
|
43925
|
+
video_editor_read_timeline: "Read the live browser Video Editor timeline, captured selection, assets and revision. Use editor_session_id from the editor context attachment. Omit request_id only for a new task; retain it through clarifications even when selection changes. Small default reads contain the full scene; large reads return selected clips or a first scene page. Use view=summary for paged tracks/counts, view=clips for details, scope=scene|selection, clip_ids and time_range to filter. view=assets pages the entire asset library. Continue with next_read plus editor_session_id; keep its request_id, expected_revision, view, scope and filters. offset/limit page entries for that view. Long text has a text_window; continue with view=clips, one clip_id, text_offset and expected_revision. Partial clip previews must not replace whole clips. IDs and absolute indexes remain valid only for the returned revision. Filters do not expand edit permission. No selection is needed for additions. This is not a local disk project. Read before any timeline edit.",
|
|
43554
43926
|
video_editor_apply_timeline: "Apply native clip, caption, effect or transition changes to the captured browser timeline. Requires editor_session_id, request_id and expected_revision from read_timeline. Use a unique operation_id and reuse it on retry. The editor validates scope, locks and revision, applies one undoable operation and confirms it before success is returned. Never substitute a standalone file or another project.",
|
|
43555
43927
|
video_editor_attach_result: "Attach a generated video to its source clip in the live browser timeline. Use editor_session_id and request_id from context. Provide the real job_id immediately for progress and automatic placement, or an uploaded HTTPS result_url and stable result_id. range: source preserves trim/speed, clip is an already trimmed result, extend adds duration. Original stays unchanged. Read the timeline to confirm placement after generation finishes."
|
|
43556
43928
|
};
|
|
@@ -44143,7 +44515,7 @@ function createEditorUpdates(options, start = (done) => new Promise((resolve3, r
|
|
|
44143
44515
|
}
|
|
44144
44516
|
}
|
|
44145
44517
|
return {
|
|
44146
|
-
runningVersion: options?.version ?? "1.0.
|
|
44518
|
+
runningVersion: options?.version ?? "1.0.4" ?? "Source checkout",
|
|
44147
44519
|
readyVersion: options && selectedDist(options) !== options.dist ? state.active : null,
|
|
44148
44520
|
channel: options?.channel ?? null,
|
|
44149
44521
|
supported: options !== null,
|
|
@@ -44207,7 +44579,7 @@ var handle = serveStdio(
|
|
|
44207
44579
|
const server = new McpServer(
|
|
44208
44580
|
{
|
|
44209
44581
|
name: "Higgsfield Video Editor (local)",
|
|
44210
|
-
version: "1.0.
|
|
44582
|
+
version: "1.0.4"
|
|
44211
44583
|
},
|
|
44212
44584
|
{ instructions: VIDEO_EDITOR_LOCAL_INSTRUCTIONS }
|
|
44213
44585
|
);
|