@cydm/pie 2.5.2 → 2.6.1
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/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/computer-use/index.js +10 -3
- package/dist/builtin/extensions/mcp-adapter/index.js +38 -16
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +8 -5
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +194 -40
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{cli-EJ5MQZNA.js → cli-GB37NZHQ.js} +2 -2
- package/dist/builtin/skills/tui-use/SKILL.md +44 -0
- package/dist/builtin/skills/tui-use/tui-use-cli.cjs +15 -7
- package/dist/chunks/{chunk-M4OJARWJ.js → chunk-3F5ZP2CV.js} +1 -1
- package/dist/chunks/{chunk-LO2V5DZZ.js → chunk-IKLQHWY2.js} +400 -73
- package/dist/chunks/{chunk-UD7KYQ6J.js → chunk-O2DKMLNX.js} +146 -11
- package/dist/chunks/{chunk-RTTGO2A6.js → chunk-Y4CYXJR7.js} +27 -2
- package/dist/chunks/src-VCWCE7YV.js +20 -0
- package/dist/chunks/{test-stream-LFR6GSKQ.js → test-stream-GOSEWMJ3.js} +1 -1
- package/dist/cli.js +26 -21
- package/package.json +2 -2
- package/dist/chunks/src-33WRCQWX.js +0 -14
|
@@ -16019,6 +16019,9 @@ var Protocol = class {
|
|
|
16019
16019
|
this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
|
|
16020
16020
|
const handleTaskResult = async () => {
|
|
16021
16021
|
const taskId = request.params.taskId;
|
|
16022
|
+
if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
|
|
16023
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
16024
|
+
}
|
|
16022
16025
|
if (this._taskMessageQueue) {
|
|
16023
16026
|
let queuedMessage;
|
|
16024
16027
|
while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
|
|
@@ -16049,12 +16052,12 @@ var Protocol = class {
|
|
|
16049
16052
|
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
|
|
16050
16053
|
}
|
|
16051
16054
|
if (!isTerminal(task.status)) {
|
|
16052
|
-
await this._waitForTaskUpdate(taskId, extra.signal);
|
|
16055
|
+
await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
|
|
16053
16056
|
return await handleTaskResult();
|
|
16054
16057
|
}
|
|
16055
16058
|
if (isTerminal(task.status)) {
|
|
16056
16059
|
const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
|
|
16057
|
-
this._clearTaskQueue(taskId);
|
|
16060
|
+
this._clearTaskQueue(taskId, extra.sessionId);
|
|
16058
16061
|
return {
|
|
16059
16062
|
...result,
|
|
16060
16063
|
_meta: {
|
|
@@ -16091,7 +16094,7 @@ var Protocol = class {
|
|
|
16091
16094
|
throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
|
|
16092
16095
|
}
|
|
16093
16096
|
await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
|
|
16094
|
-
this._clearTaskQueue(request.params.taskId);
|
|
16097
|
+
this._clearTaskQueue(request.params.taskId, extra.sessionId);
|
|
16095
16098
|
const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
|
|
16096
16099
|
if (!cancelledTask) {
|
|
16097
16100
|
throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
|
|
@@ -16219,6 +16222,19 @@ var Protocol = class {
|
|
|
16219
16222
|
const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
|
|
16220
16223
|
const capturedTransport = this._transport;
|
|
16221
16224
|
const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
|
|
16225
|
+
const sessionId = capturedTransport?.sessionId;
|
|
16226
|
+
const store = this._taskStore;
|
|
16227
|
+
let relatedTaskFound = true;
|
|
16228
|
+
let relatedTaskLookup;
|
|
16229
|
+
if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
|
|
16230
|
+
relatedTaskFound = false;
|
|
16231
|
+
relatedTaskLookup = (async () => {
|
|
16232
|
+
if (!await store.getTask(relatedTaskId, sessionId)) {
|
|
16233
|
+
throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
|
|
16234
|
+
}
|
|
16235
|
+
relatedTaskFound = true;
|
|
16236
|
+
})();
|
|
16237
|
+
}
|
|
16222
16238
|
if (handler === void 0) {
|
|
16223
16239
|
const errorResponse = {
|
|
16224
16240
|
jsonrpc: "2.0",
|
|
@@ -16228,7 +16244,10 @@ var Protocol = class {
|
|
|
16228
16244
|
message: "Method not found"
|
|
16229
16245
|
}
|
|
16230
16246
|
};
|
|
16231
|
-
if (relatedTaskId &&
|
|
16247
|
+
if (relatedTaskId && relatedTaskLookup) {
|
|
16248
|
+
const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
|
|
16249
|
+
relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error2) => this._onerror(new Error(`Failed to send an error response: ${error2}`)));
|
|
16250
|
+
} else if (relatedTaskId && this._taskMessageQueue) {
|
|
16232
16251
|
this._enqueueTaskMessage(relatedTaskId, {
|
|
16233
16252
|
type: "error",
|
|
16234
16253
|
message: errorResponse,
|
|
@@ -16279,7 +16298,10 @@ var Protocol = class {
|
|
|
16279
16298
|
closeSSEStream: extra?.closeSSEStream,
|
|
16280
16299
|
closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
|
|
16281
16300
|
};
|
|
16282
|
-
Promise.resolve().then(() => {
|
|
16301
|
+
(relatedTaskLookup ?? Promise.resolve()).then(() => {
|
|
16302
|
+
if (relatedTaskLookup && abortController.signal.aborted) {
|
|
16303
|
+
throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
|
|
16304
|
+
}
|
|
16283
16305
|
if (taskCreationParams) {
|
|
16284
16306
|
this.assertTaskHandlerCapability(request.method);
|
|
16285
16307
|
}
|
|
@@ -16314,7 +16336,7 @@ var Protocol = class {
|
|
|
16314
16336
|
...error2["data"] !== void 0 && { data: error2["data"] }
|
|
16315
16337
|
}
|
|
16316
16338
|
};
|
|
16317
|
-
if (relatedTaskId && this._taskMessageQueue) {
|
|
16339
|
+
if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
|
|
16318
16340
|
await this._enqueueTaskMessage(relatedTaskId, {
|
|
16319
16341
|
type: "error",
|
|
16320
16342
|
message: errorResponse,
|
|
@@ -16794,7 +16816,7 @@ var Protocol = class {
|
|
|
16794
16816
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
16795
16817
|
}
|
|
16796
16818
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
16797
|
-
await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
|
|
16819
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
|
|
16798
16820
|
}
|
|
16799
16821
|
/**
|
|
16800
16822
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
@@ -16823,12 +16845,13 @@ var Protocol = class {
|
|
|
16823
16845
|
* Uses polling to check for updates at the task's configured poll interval.
|
|
16824
16846
|
* @param taskId The task ID to wait for
|
|
16825
16847
|
* @param signal Abort signal to cancel the wait
|
|
16848
|
+
* @param sessionId Session of the request that waits, passed to the task store
|
|
16826
16849
|
* @returns Promise that resolves when an update occurs or rejects if aborted
|
|
16827
16850
|
*/
|
|
16828
|
-
async _waitForTaskUpdate(taskId, signal) {
|
|
16851
|
+
async _waitForTaskUpdate(taskId, signal, sessionId) {
|
|
16829
16852
|
let interval = this._options?.defaultTaskPollInterval ?? 1e3;
|
|
16830
16853
|
try {
|
|
16831
|
-
const task = await this._taskStore?.getTask(taskId);
|
|
16854
|
+
const task = await this._taskStore?.getTask(taskId, sessionId);
|
|
16832
16855
|
if (task?.pollInterval) {
|
|
16833
16856
|
interval = task.pollInterval;
|
|
16834
16857
|
}
|
|
@@ -17956,6 +17979,68 @@ function createFetchWithInit(baseFetch = fetch, baseInit) {
|
|
|
17956
17979
|
return baseFetch(url2, mergedInit);
|
|
17957
17980
|
};
|
|
17958
17981
|
}
|
|
17982
|
+
var MAX_REDIRECTS = 5;
|
|
17983
|
+
var REDIRECT_STATUSES = [301, 302, 303, 307, 308];
|
|
17984
|
+
function isWithinOrigin(from, to) {
|
|
17985
|
+
if (from.protocol === to.protocol && from.hostname === to.hostname && from.port === to.port) {
|
|
17986
|
+
return true;
|
|
17987
|
+
}
|
|
17988
|
+
return from.hostname === to.hostname && from.protocol === "http:" && from.port === "" && to.protocol === "https:" && to.port === "";
|
|
17989
|
+
}
|
|
17990
|
+
function redirectTarget(response, requestUrl) {
|
|
17991
|
+
const location = REDIRECT_STATUSES.includes(response.status) ? response.headers.get("location") : null;
|
|
17992
|
+
try {
|
|
17993
|
+
return location ? new URL(location, requestUrl) : void 0;
|
|
17994
|
+
} catch {
|
|
17995
|
+
return void 0;
|
|
17996
|
+
}
|
|
17997
|
+
}
|
|
17998
|
+
function followWithinOrigin(baseFetch, url2, init, response, followed = 0) {
|
|
17999
|
+
const target = redirectTarget(response, url2);
|
|
18000
|
+
const keepsMethod = response.status === 307 || response.status === 308 || (init?.method ?? "GET").toUpperCase() === "GET";
|
|
18001
|
+
if (!target || followed === MAX_REDIRECTS || !keepsMethod) {
|
|
18002
|
+
return void 0;
|
|
18003
|
+
}
|
|
18004
|
+
const from = new URL(url2);
|
|
18005
|
+
const addsUserinfo = (target.username || target.password) && (target.username !== from.username || target.password !== from.password);
|
|
18006
|
+
if (addsUserinfo || !isWithinOrigin(from, target)) {
|
|
18007
|
+
return void 0;
|
|
18008
|
+
}
|
|
18009
|
+
return Promise.resolve(response.body?.cancel()).then(() => baseFetch(target, { ...init, redirect: "manual" })).then((next) => followWithinOrigin(baseFetch, target, init, next, followed + 1) ?? next);
|
|
18010
|
+
}
|
|
18011
|
+
var followingFetches = /* @__PURE__ */ new WeakSet();
|
|
18012
|
+
function fetchLeavingRedirects(baseFetch) {
|
|
18013
|
+
const following = (url2, init) => (baseFetch ?? fetch)(url2, init);
|
|
18014
|
+
followingFetches.add(following);
|
|
18015
|
+
return following;
|
|
18016
|
+
}
|
|
18017
|
+
function fetchWithinOrigin(baseFetch = fetch) {
|
|
18018
|
+
if (followingFetches.has(baseFetch)) {
|
|
18019
|
+
return baseFetch;
|
|
18020
|
+
}
|
|
18021
|
+
return (url2, init) => {
|
|
18022
|
+
if (init?.redirect === "error" || init?.redirect === "manual") {
|
|
18023
|
+
return baseFetch(url2, init);
|
|
18024
|
+
}
|
|
18025
|
+
return Promise.resolve(baseFetch(url2, { ...init, redirect: "manual" })).then((response) => followWithinOrigin(baseFetch, url2, init, response) ?? response);
|
|
18026
|
+
};
|
|
18027
|
+
}
|
|
18028
|
+
function unfollowedRedirect(response, requestUrl) {
|
|
18029
|
+
if (response.type === "opaqueredirect") {
|
|
18030
|
+
return "Redirect not followed: this runtime does not expose the redirect target";
|
|
18031
|
+
}
|
|
18032
|
+
const from = response.url || requestUrl;
|
|
18033
|
+
const target = redirectTarget(response, from);
|
|
18034
|
+
if (!target) {
|
|
18035
|
+
return void 0;
|
|
18036
|
+
}
|
|
18037
|
+
target.username = target.password = target.search = target.hash = "";
|
|
18038
|
+
if (target.protocol === "http:" && new URL(from).protocol === "https:") {
|
|
18039
|
+
target.protocol = "https:";
|
|
18040
|
+
return `Redirect to plain http not followed; try ${target.href} instead`;
|
|
18041
|
+
}
|
|
18042
|
+
return `Redirect to ${target.href} not followed`;
|
|
18043
|
+
}
|
|
17959
18044
|
|
|
17960
18045
|
// ../../node_modules/pkce-challenge/dist/index.node.js
|
|
17961
18046
|
var crypto;
|
|
@@ -18102,7 +18187,12 @@ var OAuthTokensSchema = object2({
|
|
|
18102
18187
|
token_type: string2(),
|
|
18103
18188
|
expires_in: coerce_exports.number().optional(),
|
|
18104
18189
|
scope: string2().optional(),
|
|
18105
|
-
refresh_token: string2().optional()
|
|
18190
|
+
refresh_token: string2().optional(),
|
|
18191
|
+
/**
|
|
18192
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
18193
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
18194
|
+
*/
|
|
18195
|
+
issuer: string2().optional().catch(void 0)
|
|
18106
18196
|
}).strip();
|
|
18107
18197
|
var OAuthErrorResponseSchema = object2({
|
|
18108
18198
|
error: string2(),
|
|
@@ -18132,7 +18222,12 @@ var OAuthClientInformationSchema = object2({
|
|
|
18132
18222
|
client_id: string2(),
|
|
18133
18223
|
client_secret: string2().optional(),
|
|
18134
18224
|
client_id_issued_at: number2().optional(),
|
|
18135
|
-
client_secret_expires_at: number2().optional()
|
|
18225
|
+
client_secret_expires_at: number2().optional(),
|
|
18226
|
+
/**
|
|
18227
|
+
* Not part of the wire format: the authorization server this value was obtained from, added by
|
|
18228
|
+
* the client's `auth()` before it is stored and compared when it is read back.
|
|
18229
|
+
*/
|
|
18230
|
+
issuer: string2().optional().catch(void 0)
|
|
18136
18231
|
}).strip();
|
|
18137
18232
|
var OAuthClientInformationFullSchema = OAuthClientMetadataSchema.merge(OAuthClientInformationSchema);
|
|
18138
18233
|
var OAuthClientRegistrationErrorSchema = object2({
|
|
@@ -18330,10 +18425,31 @@ async function parseErrorResponse(input) {
|
|
|
18330
18425
|
const errorClass = OAUTH_ERRORS[error2] || ServerError;
|
|
18331
18426
|
return new errorClass(error_description || "", error_uri);
|
|
18332
18427
|
} catch (error2) {
|
|
18333
|
-
const
|
|
18428
|
+
const redirect = input instanceof Response ? unfollowedRedirect(input, input.url) : void 0;
|
|
18429
|
+
const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ""}${redirect ?? `Invalid OAuth error response: ${error2}. Raw body: ${body}`}`;
|
|
18334
18430
|
return new ServerError(errorMessage);
|
|
18335
18431
|
}
|
|
18336
18432
|
}
|
|
18433
|
+
function issuersMatch(a, b) {
|
|
18434
|
+
let [x, y] = [a, b];
|
|
18435
|
+
try {
|
|
18436
|
+
[x, y] = [new URL(a).href, new URL(b).href];
|
|
18437
|
+
} catch {
|
|
18438
|
+
}
|
|
18439
|
+
return x === y || x.endsWith("/") && x.slice(0, -1) === y || y.endsWith("/") && y.slice(0, -1) === x;
|
|
18440
|
+
}
|
|
18441
|
+
function discardIfIssuerMismatch(stored, issuer) {
|
|
18442
|
+
if (!stored)
|
|
18443
|
+
return void 0;
|
|
18444
|
+
if (typeof stored.issuer !== "string")
|
|
18445
|
+
return stored.issuer == null ? stored : { ...stored, issuer: void 0 };
|
|
18446
|
+
return issuersMatch(stored.issuer, issuer) ? stored : void 0;
|
|
18447
|
+
}
|
|
18448
|
+
var TokenResponseSchema = OAuthTokensSchema.omit({ issuer: true });
|
|
18449
|
+
var RegistrationResponseSchema = OAuthClientInformationFullSchema.omit({ issuer: true });
|
|
18450
|
+
function boundElsewhereError(stored, issuer) {
|
|
18451
|
+
return new Error(`OAuth client information is bound to authorization server ${stored.issuer} and is not presented to ${issuer}. Clear the stored client information, or correct \`expectedIssuer\`, if the authorization server has moved.`);
|
|
18452
|
+
}
|
|
18337
18453
|
async function auth(provider, options) {
|
|
18338
18454
|
try {
|
|
18339
18455
|
return await authInternal(provider, options);
|
|
@@ -18387,10 +18503,24 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
18387
18503
|
authorizationServerMetadata: metadata
|
|
18388
18504
|
});
|
|
18389
18505
|
}
|
|
18506
|
+
const issuer = String(authorizationServerUrl);
|
|
18390
18507
|
const selectedResource = await selectResourceURL(serverUrl, provider, resourceMetadata);
|
|
18391
18508
|
const resource = selectedResource && resourceMetadata && !provider.validateResourceURL ? resourceMetadata.resource : selectedResource;
|
|
18392
18509
|
const resolvedScope = scope || resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
|
|
18393
|
-
|
|
18510
|
+
const storedClientInformation = await Promise.resolve(provider.clientInformation());
|
|
18511
|
+
let clientInformation = discardIfIssuerMismatch(storedClientInformation, issuer);
|
|
18512
|
+
const canRegisterAgain = provider.saveClientInformation !== void 0 && !!provider.redirectUrl;
|
|
18513
|
+
if (storedClientInformation && !clientInformation && !canRegisterAgain) {
|
|
18514
|
+
throw boundElsewhereError(storedClientInformation, issuer);
|
|
18515
|
+
}
|
|
18516
|
+
const unstampedClientInformation = clientInformation?.issuer == null ? clientInformation : void 0;
|
|
18517
|
+
const bindClientInformation = async () => {
|
|
18518
|
+
try {
|
|
18519
|
+
if (unstampedClientInformation)
|
|
18520
|
+
await provider.saveClientInformation?.({ ...unstampedClientInformation, issuer });
|
|
18521
|
+
} catch {
|
|
18522
|
+
}
|
|
18523
|
+
};
|
|
18394
18524
|
if (!clientInformation) {
|
|
18395
18525
|
if (authorizationCode !== void 0) {
|
|
18396
18526
|
throw new Error("Existing OAuth client information is required when exchanging an authorization code");
|
|
@@ -18402,9 +18532,7 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
18402
18532
|
}
|
|
18403
18533
|
const shouldUseUrlBasedClientId = supportsUrlBasedClientId && clientMetadataUrl;
|
|
18404
18534
|
if (shouldUseUrlBasedClientId) {
|
|
18405
|
-
clientInformation = {
|
|
18406
|
-
client_id: clientMetadataUrl
|
|
18407
|
-
};
|
|
18535
|
+
clientInformation = { client_id: clientMetadataUrl, issuer };
|
|
18408
18536
|
await provider.saveClientInformation?.(clientInformation);
|
|
18409
18537
|
} else {
|
|
18410
18538
|
if (!provider.saveClientInformation) {
|
|
@@ -18416,8 +18544,8 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
18416
18544
|
scope: resolvedScope,
|
|
18417
18545
|
fetchFn
|
|
18418
18546
|
});
|
|
18419
|
-
|
|
18420
|
-
clientInformation
|
|
18547
|
+
clientInformation = { ...fullInformation, issuer };
|
|
18548
|
+
await provider.saveClientInformation(clientInformation);
|
|
18421
18549
|
}
|
|
18422
18550
|
}
|
|
18423
18551
|
const nonInteractiveFlow = !provider.redirectUrl;
|
|
@@ -18428,10 +18556,14 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
18428
18556
|
authorizationCode,
|
|
18429
18557
|
fetchFn
|
|
18430
18558
|
});
|
|
18431
|
-
await
|
|
18559
|
+
await bindClientInformation();
|
|
18560
|
+
await provider.saveTokens({ ...tokens2, issuer });
|
|
18432
18561
|
return "AUTHORIZED";
|
|
18433
18562
|
}
|
|
18434
|
-
const tokens = await provider.tokens();
|
|
18563
|
+
const tokens = discardIfIssuerMismatch(await provider.tokens(), issuer);
|
|
18564
|
+
if (tokens?.refresh_token && tokens.issuer == null) {
|
|
18565
|
+
console.warn("[mcp-sdk] stored OAuth tokens have no 'issuer' property (saved by an earlier version, or by a provider that does not keep it) and are used as-is; make sure your OAuthClientProvider stores what saveTokens() and saveClientInformation() receive unchanged.");
|
|
18566
|
+
}
|
|
18435
18567
|
if (tokens?.refresh_token) {
|
|
18436
18568
|
try {
|
|
18437
18569
|
const newTokens = await refreshAuthorization(authorizationServerUrl, {
|
|
@@ -18442,7 +18574,8 @@ async function authInternal(provider, { serverUrl, authorizationCode, scope, res
|
|
|
18442
18574
|
addClientAuthentication: provider.addClientAuthentication,
|
|
18443
18575
|
fetchFn
|
|
18444
18576
|
});
|
|
18445
|
-
await
|
|
18577
|
+
await bindClientInformation();
|
|
18578
|
+
await provider.saveTokens({ ...newTokens, issuer });
|
|
18446
18579
|
return "AUTHORIZED";
|
|
18447
18580
|
} catch (error2) {
|
|
18448
18581
|
if (!(error2 instanceof OAuthError) || error2 instanceof ServerError) {
|
|
@@ -18541,7 +18674,7 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn =
|
|
|
18541
18674
|
}
|
|
18542
18675
|
async function fetchWithCorsRetry(url2, headers, fetchFn = fetch) {
|
|
18543
18676
|
try {
|
|
18544
|
-
return await fetchFn(url2, { headers });
|
|
18677
|
+
return await fetchWithinOrigin(fetchFn)(url2, { headers });
|
|
18545
18678
|
} catch (error2) {
|
|
18546
18679
|
if (error2 instanceof TypeError) {
|
|
18547
18680
|
if (headers) {
|
|
@@ -18566,7 +18699,7 @@ async function tryMetadataDiscovery(url2, protocolVersion, fetchFn = fetch) {
|
|
|
18566
18699
|
return await fetchWithCorsRetry(url2, headers, fetchFn);
|
|
18567
18700
|
}
|
|
18568
18701
|
function shouldAttemptFallback(response, pathname) {
|
|
18569
|
-
return !response || response.
|
|
18702
|
+
return !response || !response.ok && response.status < 500 && pathname !== "/";
|
|
18570
18703
|
}
|
|
18571
18704
|
async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
|
|
18572
18705
|
const issuer = new URL(serverUrl);
|
|
@@ -18632,7 +18765,7 @@ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fet
|
|
|
18632
18765
|
}
|
|
18633
18766
|
if (!response.ok) {
|
|
18634
18767
|
await response.body?.cancel();
|
|
18635
|
-
if (response.status
|
|
18768
|
+
if (response.status < 500) {
|
|
18636
18769
|
continue;
|
|
18637
18770
|
}
|
|
18638
18771
|
throw new Error(`HTTP ${response.status} trying to load ${type === "oauth" ? "OAuth" : "OpenID provider"} metadata from ${endpointUrl}`);
|
|
@@ -18727,7 +18860,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
18727
18860
|
const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
|
|
18728
18861
|
applyClientAuthentication(authMethod, clientInformation, headers, tokenRequestParams);
|
|
18729
18862
|
}
|
|
18730
|
-
const response = await (fetchFn ?? fetch)(tokenUrl, {
|
|
18863
|
+
const response = await fetchWithinOrigin(fetchFn ?? fetch)(tokenUrl, {
|
|
18731
18864
|
method: "POST",
|
|
18732
18865
|
headers,
|
|
18733
18866
|
body: tokenRequestParams
|
|
@@ -18735,7 +18868,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
18735
18868
|
if (!response.ok) {
|
|
18736
18869
|
throw await parseErrorResponse(response);
|
|
18737
18870
|
}
|
|
18738
|
-
return
|
|
18871
|
+
return TokenResponseSchema.parse(await response.json());
|
|
18739
18872
|
}
|
|
18740
18873
|
async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
|
|
18741
18874
|
const tokenRequestParams = new URLSearchParams({
|
|
@@ -18753,6 +18886,15 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
|
|
|
18753
18886
|
return { refresh_token: refreshToken, ...tokens };
|
|
18754
18887
|
}
|
|
18755
18888
|
async function fetchToken(provider, authorizationServerUrl, { metadata, resource, authorizationCode, fetchFn } = {}) {
|
|
18889
|
+
const readClientInformation = async () => {
|
|
18890
|
+
const storedClientInformation = await provider.clientInformation();
|
|
18891
|
+
const checked = discardIfIssuerMismatch(storedClientInformation, String(authorizationServerUrl));
|
|
18892
|
+
if (storedClientInformation && !checked) {
|
|
18893
|
+
throw boundElsewhereError(storedClientInformation, String(authorizationServerUrl));
|
|
18894
|
+
}
|
|
18895
|
+
return checked;
|
|
18896
|
+
};
|
|
18897
|
+
let clientInformation = await readClientInformation();
|
|
18756
18898
|
const scope = provider.clientMetadata.scope;
|
|
18757
18899
|
let tokenRequestParams;
|
|
18758
18900
|
if (provider.prepareTokenRequest) {
|
|
@@ -18768,11 +18910,11 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
18768
18910
|
const codeVerifier = await provider.codeVerifier();
|
|
18769
18911
|
tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, provider.redirectUrl);
|
|
18770
18912
|
}
|
|
18771
|
-
|
|
18913
|
+
clientInformation ?? (clientInformation = await readClientInformation());
|
|
18772
18914
|
return executeTokenRequest(authorizationServerUrl, {
|
|
18773
18915
|
metadata,
|
|
18774
18916
|
tokenRequestParams,
|
|
18775
|
-
clientInformation
|
|
18917
|
+
clientInformation,
|
|
18776
18918
|
addClientAuthentication: provider.addClientAuthentication,
|
|
18777
18919
|
resource,
|
|
18778
18920
|
fetchFn
|
|
@@ -18788,7 +18930,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
18788
18930
|
} else {
|
|
18789
18931
|
registrationUrl = new URL("/register", authorizationServerUrl);
|
|
18790
18932
|
}
|
|
18791
|
-
const response = await (fetchFn ?? fetch)(registrationUrl, {
|
|
18933
|
+
const response = await fetchWithinOrigin(fetchFn ?? fetch)(registrationUrl, {
|
|
18792
18934
|
method: "POST",
|
|
18793
18935
|
headers: {
|
|
18794
18936
|
"Content-Type": "application/json"
|
|
@@ -18801,7 +18943,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
18801
18943
|
if (!response.ok) {
|
|
18802
18944
|
throw await parseErrorResponse(response);
|
|
18803
18945
|
}
|
|
18804
|
-
return
|
|
18946
|
+
return RegistrationResponseSchema.parse(await response.json());
|
|
18805
18947
|
}
|
|
18806
18948
|
|
|
18807
18949
|
// ../../node_modules/eventsource-parser/dist/index.js
|
|
@@ -19028,9 +19170,19 @@ var StreamableHTTPClientTransport = class {
|
|
|
19028
19170
|
this._authProvider = opts?.authProvider;
|
|
19029
19171
|
this._fetch = opts?.fetch;
|
|
19030
19172
|
this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
|
|
19173
|
+
this._followRedirects = opts?.redirectPolicy === "follow";
|
|
19174
|
+
if (this._followRedirects) {
|
|
19175
|
+
this._fetch = fetchLeavingRedirects(this._fetch);
|
|
19176
|
+
this._fetchWithInit = fetchLeavingRedirects(this._fetchWithInit);
|
|
19177
|
+
}
|
|
19031
19178
|
this._sessionId = opts?.sessionId;
|
|
19032
19179
|
this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
|
19033
19180
|
}
|
|
19181
|
+
/** Error text for a redirect `response` that was not followed, or `undefined` for any other response. */
|
|
19182
|
+
_unfollowedRedirect(response, url2) {
|
|
19183
|
+
const text = unfollowedRedirect(response, url2);
|
|
19184
|
+
return text && !this._followRedirects ? `${text} (redirectPolicy: 'same-origin')` : text;
|
|
19185
|
+
}
|
|
19034
19186
|
async _authThenStart() {
|
|
19035
19187
|
if (!this._authProvider) {
|
|
19036
19188
|
throw new UnauthorizedError("No auth provider");
|
|
@@ -19080,11 +19232,13 @@ var StreamableHTTPClientTransport = class {
|
|
|
19080
19232
|
if (resumptionToken) {
|
|
19081
19233
|
headers.set("last-event-id", resumptionToken);
|
|
19082
19234
|
}
|
|
19083
|
-
const
|
|
19084
|
-
|
|
19085
|
-
|
|
19086
|
-
|
|
19087
|
-
|
|
19235
|
+
const fetchFn = this._fetch ?? fetch;
|
|
19236
|
+
const init = { method: "GET", headers, signal: this._abortController?.signal };
|
|
19237
|
+
let response = await fetchFn(this._url, this._followRedirects ? init : { ...init, redirect: "manual" });
|
|
19238
|
+
const followed = this._followRedirects ? void 0 : followWithinOrigin(fetchFn, this._url, init, response);
|
|
19239
|
+
if (followed) {
|
|
19240
|
+
response = await followed;
|
|
19241
|
+
}
|
|
19088
19242
|
if (!response.ok) {
|
|
19089
19243
|
await response.body?.cancel();
|
|
19090
19244
|
if (response.status === 401 && this._authProvider) {
|
|
@@ -19093,7 +19247,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
19093
19247
|
if (response.status === 405) {
|
|
19094
19248
|
return;
|
|
19095
19249
|
}
|
|
19096
|
-
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
|
|
19250
|
+
throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${this._unfollowedRedirect(response, this._url) ?? response.statusText}`);
|
|
19097
19251
|
}
|
|
19098
19252
|
this._handleSseStream(response.body, options, true);
|
|
19099
19253
|
} catch (error2) {
|
|
@@ -19256,7 +19410,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
19256
19410
|
body: JSON.stringify(message),
|
|
19257
19411
|
signal: this._abortController?.signal
|
|
19258
19412
|
};
|
|
19259
|
-
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
19413
|
+
const response = await fetchWithinOrigin(this._fetch ?? fetch)(this._url, init);
|
|
19260
19414
|
const sessionId = response.headers.get("mcp-session-id");
|
|
19261
19415
|
if (sessionId) {
|
|
19262
19416
|
this._sessionId = sessionId;
|
|
@@ -19308,7 +19462,7 @@ var StreamableHTTPClientTransport = class {
|
|
|
19308
19462
|
return this.send(message);
|
|
19309
19463
|
}
|
|
19310
19464
|
}
|
|
19311
|
-
throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
|
|
19465
|
+
throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${this._unfollowedRedirect(response, this._url) ?? text}`);
|
|
19312
19466
|
}
|
|
19313
19467
|
this._hasCompletedAuthFlow = false;
|
|
19314
19468
|
this._lastUpscopingHeader = void 0;
|
|
@@ -19370,10 +19524,10 @@ var StreamableHTTPClientTransport = class {
|
|
|
19370
19524
|
headers,
|
|
19371
19525
|
signal: this._abortController?.signal
|
|
19372
19526
|
};
|
|
19373
|
-
const response = await (this._fetch ?? fetch)(this._url, init);
|
|
19527
|
+
const response = await fetchWithinOrigin(this._fetch ?? fetch)(this._url, init);
|
|
19374
19528
|
await response.body?.cancel();
|
|
19375
19529
|
if (!response.ok && response.status !== 405) {
|
|
19376
|
-
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
|
|
19530
|
+
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${this._unfollowedRedirect(response, this._url) ?? response.statusText}`);
|
|
19377
19531
|
}
|
|
19378
19532
|
this._sessionId = void 0;
|
|
19379
19533
|
} catch (error2) {
|
|
@@ -21,6 +21,6 @@ function tryFastPath(argv, options) {
|
|
|
21
21
|
|
|
22
22
|
// vendor/chrome-devtools-axi/bin/chrome-devtools-axi.ts
|
|
23
23
|
if (!tryFastPath(process.argv.slice(2), { version: VERSION })) {
|
|
24
|
-
const { main } = await import("./cli-
|
|
24
|
+
const { main } = await import("./cli-GB37NZHQ.js");
|
|
25
25
|
await main(process.argv.slice(2));
|
|
26
26
|
}
|
|
@@ -1845,8 +1845,8 @@ function isProcessAlive(pid) {
|
|
|
1845
1845
|
try {
|
|
1846
1846
|
process.kill(pid, 0);
|
|
1847
1847
|
return true;
|
|
1848
|
-
} catch {
|
|
1849
|
-
return
|
|
1848
|
+
} catch (error) {
|
|
1849
|
+
return error?.code !== "ESRCH";
|
|
1850
1850
|
}
|
|
1851
1851
|
}
|
|
1852
1852
|
function httpGet(port, path, timeoutMs = 2e3) {
|
|
@@ -50,10 +50,54 @@ tui-use daemon stop
|
|
|
50
50
|
- Send an explicit `press enter` after typing when reliable submission matters.
|
|
51
51
|
- `wait --text` exits non-zero if the requested pattern is absent at the deadline.
|
|
52
52
|
Read the returned screen and fix the input instead of assuming the wait succeeded.
|
|
53
|
+
Do not rerun the identical failing wait; poll with `--poll` (below) or change the input.
|
|
53
54
|
- Use `wait --exit` to confirm process termination. Seeing the last output or
|
|
54
55
|
leaving fullscreen does not by itself mean the process has exited.
|
|
55
56
|
- Kill only sessions you created. Do not restart or stop a daemon that owns another task's live sessions.
|
|
56
57
|
|
|
58
|
+
## Bounded Polling For Long Tasks
|
|
59
|
+
|
|
60
|
+
For work that legitimately takes longer than one wait, opt in to poll mode:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
tui-use --session <id> wait 20000 --text "DONE_MARKER" --poll --format json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- `wait_state: "satisfied"` (exit 0): the marker appeared, or `--exit` saw the exit.
|
|
67
|
+
With `--exit` this means termination was observed, not that the program
|
|
68
|
+
succeeded: read `exit_code`, which can be nonzero.
|
|
69
|
+
- `wait_state: "pending"` (exit 0): the deadline passed while the process is still
|
|
70
|
+
running. This only means the PTY is alive; it is not evidence of progress.
|
|
71
|
+
- `wait_state: "failed"` (exit 1): the session exited without the `--text` marker.
|
|
72
|
+
Daemon, session and argument errors also exit 1. Never treat these as pending.
|
|
73
|
+
|
|
74
|
+
Set a total budget before polling (for example at most 6 polls or 10 minutes).
|
|
75
|
+
After each pending poll compare the `screen` with the previous poll. If the
|
|
76
|
+
screen is unchanged across two or three polls, or the budget is spent, stop and
|
|
77
|
+
report the task as not progressing, with the last screen, instead of polling on.
|
|
78
|
+
For programs that can emit structured output, prefer that over viewport text.
|
|
79
|
+
|
|
80
|
+
## Waiting On Pie Tasks
|
|
81
|
+
|
|
82
|
+
To run or supervise a Pie task, use the JSONL protocol over pipes instead of
|
|
83
|
+
driving the Pie TUI through this skill and reading its viewport:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
pie chat --json-events # stdin: one JSON request per line; stdout: one JSON event per line
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- Wait for `agent.ready`, then send
|
|
90
|
+
`{"type":"turn.request","turnId":"t1","prompt":"..."}`.
|
|
91
|
+
- The turn outcome is exactly one of `turn.completed`, `turn.failed`,
|
|
92
|
+
`turn.cancelled` or `turn.stalled`, followed by `turn.settled`. Decide from
|
|
93
|
+
these events, not from screen text or the process still running.
|
|
94
|
+
- `tool.started`/`tool.completed` and `turn.retry.*` events are progress
|
|
95
|
+
evidence. Pie emits `turn.stalled` after `PIE_JSON_EVENTS_NO_PROGRESS_MS`
|
|
96
|
+
(default 10 minutes) without activity.
|
|
97
|
+
- `turn.failed` after `turn.retry.exhausted`, or an exhausted-quota/balance
|
|
98
|
+
error, is terminal: report it instead of resubmitting the same prompt.
|
|
99
|
+
- Use `{"type":"turn.interrupt"}` to cancel and `{"type":"shutdown"}` to exit.
|
|
100
|
+
|
|
57
101
|
## Host Behavior
|
|
58
102
|
|
|
59
103
|
Windows defaults to native PowerShell with matching invocation arguments;
|
|
@@ -10361,8 +10361,8 @@ program2.command("snapshot").description("Return the current rendered screen sna
|
|
|
10361
10361
|
handleResponse(res, (r) => printScreen(r, opts.format));
|
|
10362
10362
|
});
|
|
10363
10363
|
program2.command("wait [duration]").description(
|
|
10364
|
-
'Wait for screen to change or timeout.\n wait \u2192 wait for screen to change (default 3000ms)\n wait 5000 \u2192 wait for 5000ms\n wait --text "pattern" \u2192 wait until screen contains text\n wait --debounce 300 \u2192 wait until screen is stable for 300ms (default: 100ms)'
|
|
10365
|
-
).option("--text <text>", "Wait until screen contains literal text").option("--regex", "Interpret --text as a regex in a bounded worker").option("--exit", "Wait for process exit instead of just a screen change").option("--debounce <ms>", "Idle time after last change before resolving, in ms (default: 100)", "100").option("--format <fmt>", "Output format: pretty, json (default: pretty)", "pretty").option("--color", "Preserve ANSI color/style escape sequences in output lines").action(async (duration, opts) => {
|
|
10364
|
+
'Wait for screen to change or timeout.\n wait \u2192 wait for screen to change (default 3000ms)\n wait 5000 \u2192 wait for 5000ms\n wait --text "pattern" \u2192 wait until screen contains text\n wait --debounce 300 \u2192 wait until screen is stable for 300ms (default: 100ms)\n wait --text "pattern" --poll \u2192 exit 0 with wait_state "pending" if the deadline passes while the session is still running'
|
|
10365
|
+
).option("--text <text>", "Wait until screen contains literal text").option("--regex", "Interpret --text as a regex in a bounded worker").option("--exit", "Wait for process exit instead of just a screen change").option("--poll", 'Bounded polling: a deadline on a still-running session reports wait_state "pending" and exits 0; an exited session that never matched --text, and errors, exit 1. With --exit, "satisfied" means termination was observed, not success: check exit_code').option("--debounce <ms>", "Idle time after last change before resolving, in ms (default: 100)", "100").option("--format <fmt>", "Output format: pretty, json (default: pretty)", "pretty").option("--color", "Preserve ANSI color/style escape sequences in output lines").action(async (duration, opts) => {
|
|
10366
10366
|
let timeoutMs = 3e3;
|
|
10367
10367
|
if (duration) {
|
|
10368
10368
|
timeoutMs = Number(duration);
|
|
@@ -10380,8 +10380,15 @@ program2.command("wait [duration]").description(
|
|
|
10380
10380
|
});
|
|
10381
10381
|
handleResponse(res, (r) => {
|
|
10382
10382
|
const screen = r;
|
|
10383
|
-
|
|
10384
|
-
|
|
10383
|
+
const conditional = opts.text !== void 0 || opts.exit;
|
|
10384
|
+
const unmet = conditional && screen.wait_satisfied === false;
|
|
10385
|
+
const pending = !!opts.poll && screen.timed_out === true && screen.status === "running" && (unmet || !conditional);
|
|
10386
|
+
const waitState = opts.poll ? pending ? "pending" : unmet ? "failed" : "satisfied" : void 0;
|
|
10387
|
+
printScreen(screen, opts.format, waitState);
|
|
10388
|
+
if (pending) {
|
|
10389
|
+
process.stderr.write(`Wait pending: ${opts.text ?? (opts.exit ? "process exit" : "screen change")} not seen before timeout; session is still running. Liveness is not evidence of progress: compare screens across polls and stop after a bounded number of unchanged polls.
|
|
10390
|
+
`);
|
|
10391
|
+
} else if (unmet) {
|
|
10385
10392
|
process.stderr.write(`Wait condition was not met${screen.timed_out ? " before timeout" : " before the session exited"}: ${opts.text ?? "process exit"}
|
|
10386
10393
|
`);
|
|
10387
10394
|
process.exitCode = 1;
|
|
@@ -10586,7 +10593,7 @@ function inputText(parts, fromStdin) {
|
|
|
10586
10593
|
if (parts.length === 0) throw new Error("Provide text arguments or --stdin.");
|
|
10587
10594
|
return parts.join(" ");
|
|
10588
10595
|
}
|
|
10589
|
-
function printScreen(r, format = "pretty") {
|
|
10596
|
+
function printScreen(r, format = "pretty", waitState) {
|
|
10590
10597
|
if (format === "json") {
|
|
10591
10598
|
console.log(
|
|
10592
10599
|
JSON.stringify(
|
|
@@ -10602,7 +10609,8 @@ function printScreen(r, format = "pretty") {
|
|
|
10602
10609
|
cols: r.cols,
|
|
10603
10610
|
rows: r.rows,
|
|
10604
10611
|
highlights: r.highlights,
|
|
10605
|
-
...r.type === "wait" ? { wait_satisfied: r.wait_satisfied, timed_out: r.timed_out } : {}
|
|
10612
|
+
...r.type === "wait" ? { wait_satisfied: r.wait_satisfied, timed_out: r.timed_out } : {},
|
|
10613
|
+
...waitState ? { wait_state: waitState } : {}
|
|
10606
10614
|
},
|
|
10607
10615
|
null,
|
|
10608
10616
|
2
|
|
@@ -10612,7 +10620,7 @@ function printScreen(r, format = "pretty") {
|
|
|
10612
10620
|
}
|
|
10613
10621
|
const width = r.cols;
|
|
10614
10622
|
const header = `\u2500\u2500\u2500 ${r.session_id} ${"\u2500".repeat(Math.max(0, width - r.session_id.length - 5))}`;
|
|
10615
|
-
const info = `${r.status} | cursor(${r.cursor.x},${r.cursor.y}) | fullscreen:${r.is_fullscreen} | title:"${r.title || ""}"`;
|
|
10623
|
+
const info = `${r.status} | cursor(${r.cursor.x},${r.cursor.y}) | fullscreen:${r.is_fullscreen} | title:"${r.title || ""}"${waitState ? ` | wait:${waitState}` : ""}`;
|
|
10616
10624
|
const footer = `\u2500\u2500\u2500 ${info} ${"\u2500".repeat(Math.max(0, width - info.length - 5))}`;
|
|
10617
10625
|
process.stdout.write(header + "\n");
|
|
10618
10626
|
for (const line of r.lines) process.stdout.write(line + "\n");
|